File Coverage

blib/lib/App/Dochazka/REST/ResourceDefs.pm
Criterion Covered Total %
statement 12 14 85.7
branch 0 2 0.0
condition n/a
subroutine 4 5 80.0
pod 1 1 100.0
total 17 22 77.2


line stmt bran cond sub pod time code
1             # *************************************************************************
2             # Copyright (c) 2014-2017, SUSE LLC
3             #
4             # All rights reserved.
5             #
6             # Redistribution and use in source and binary forms, with or without
7             # modification, are permitted provided that the following conditions are met:
8             #
9             # 1. Redistributions of source code must retain the above copyright notice,
10             # this list of conditions and the following disclaimer.
11             #
12             # 2. Redistributions in binary form must reproduce the above copyright
13             # notice, this list of conditions and the following disclaimer in the
14             # documentation and/or other materials provided with the distribution.
15             #
16             # 3. Neither the name of SUSE LLC nor the names of its contributors may be
17             # used to endorse or promote products derived from this software without
18             # specific prior written permission.
19             #
20             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23             # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24             # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25             # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26             # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27             # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28             # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29             # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30             # POSSIBILITY OF SUCH DAMAGE.
31             # *************************************************************************
32              
33             # ------------------------
34             # The purpose of this package is to hold all the resource definitions
35             # and provide a hook for loading them.
36             # ------------------------
37              
38             package App::Dochazka::REST::ResourceDefs;
39              
40 41     41   234 use strict;
  41         81  
  41         1034  
41 41     41   186 use warnings;
  41         78  
  41         945  
42              
43 41     41   183 use App::CELL qw( $log );
  41         73  
  41         2892  
44 41     41   10611 use Web::MREST::InitRouter;
  41         6167344  
  41         102469  
45              
46             my $defs;
47             my $tsrange_validation = qr/^[[(].*,.*[])]$/;
48             my $ts_validation = qr/^(\"|\')?\d+-\d+-\d+( +\d+:\d+(:\d+)?)?(\"|\')?$/;
49             my $term_validation = qr/^[[:alnum:]_][[:alnum:]_-]*$/;
50             my $date_validation = qr/^\d{2,4}-\d{1,2}-\d{1,2}$/;
51             my $priv_validation = qr/^(admin)|(active)|(inactive)|(passerby)$/i;
52             my $psqlint_validation = qr/^[[:alnum:] ]+$/;
53              
54              
55              
56              
57              
58             =head1 NAME
59              
60             App::Dochazka::REST::ResourceDefs - Resource definitions
61              
62              
63              
64              
65             =head1 DESCRIPTION
66              
67             The purpose of this package is to hold all the resource definitions
68             and provide a hook for loading them.
69              
70             =cut
71              
72              
73              
74              
75             =head1 RESOURCE DEFINITIONS
76              
77             =head2 Top-level resources
78              
79             =cut
80              
81             $defs->{'top'} = {
82              
83             # root resource
84             '/' => {
85             handler => 'handler_noop',
86             acl_profile => 'passerby',
87             description => 'The root resource',
88             documentation => <<'EOH',
89             =pod
90              
91             This resource is the parent of all resources that do not specify
92             a parent in their resource definition.
93             EOH
94             },
95              
96             # bugreport
97             'bugreport' =>
98             {
99             parent => '/',
100             handler => {
101             GET => 'handler_bugreport',
102             },
103             acl_profile => 'passerby',
104             cli => 'bugreport',
105             description => 'Display instructions for reporting bugs in Web::MREST',
106             documentation => <<'EOH',
107             =pod
108              
109             Returns a JSON structure containing instructions for reporting bugs.
110             EOH
111             },
112              
113             # configinfo
114             'configinfo' =>
115             {
116             parent => '/',
117             handler => {
118             GET => 'handler_configinfo',
119             },
120             acl_profile => 'passerby',
121             cli => 'configinfo',
122             description => 'Display information about Web::MREST configuration',
123             documentation => <<'EOH',
124             =pod
125              
126             Returns a list of directories that were scanned for configuration files.
127             EOH
128             },
129              
130             # dbstatus
131             'dbstatus' => {
132             parent => '/',
133             handler => {
134             GET => 'handler_dbstatus',
135             },
136             acl_profile => 'inactive',
137             cli => 'dbstatus',
138             description => 'Display status of database connection',
139             documentation => <<'EOH',
140             =pod
141              
142             This resource checks the employee's database connection and reports on its status.
143             The result - either "UP" or "DOWN" - will be encapsulated in a payload like this:
144              
145             { "dbstatus" : "UP" }
146              
147             Each employee gets her own database connection when she logs in to Dochazka.
148             Calling this resource causes the server to execute a 'ping' on the connection.
149             If the ping test fails, the server will attempt to open a new connection. Only
150             if this, too, fails will "DOWN" be returned.
151             EOH
152             },
153              
154             # docu
155             'docu' =>
156             {
157             parent => '/',
158             handler => 'handler_noop',
159             acl_profile => 'passerby',
160             cli => 'docu',
161             description => 'Access on-line documentation (via POST to an appropriate subresource)',
162             documentation => <<'EOH',
163             =pod
164              
165             This resource provides access to on-line documentation through its
166             subresources: 'docu/pod', 'docu/html', and 'docu/text'.
167              
168             To get documentation on a resource, send a POST reqeuest for one of
169             these subresources, including the resource name in the request
170             entity as a bare JSON string (i.e. in double quotes).
171             EOH
172             },
173              
174             # docu/pod
175             'docu/pod' =>
176             {
177             parent => 'docu',
178             handler => {
179             POST => 'handler_docu',
180             },
181             acl_profile => 'passerby',
182             cli => 'docu pod $RESOURCE',
183             description => 'Display POD documentation of a resource',
184             documentation => <<'EOH',
185             =pod
186            
187             This resource provides access to on-line help documentation in POD format.
188             It expects to find a resource name (e.g. "employee/eid/:eid" including the
189             double-quotes, and without leading or trailing slash) in the request body. It
190             returns a string containing the POD source code of the resource documentation.
191             EOH
192             },
193              
194             # docu/html
195             'docu/html' =>
196             {
197             parent => 'docu',
198             handler => {
199             POST => 'handler_docu',
200             },
201             acl_profile => 'passerby',
202             cli => 'docu html $RESOURCE',
203             description => 'Display HTML documentation of a resource',
204             documentation => <<'EOH',
205             =pod
206              
207             This resource provides access to on-line help documentation. It expects to find
208             a resource name (e.g. "employee/eid/:eid" including the double-quotes, and without
209             leading or trailing slash) in the request body. It generates HTML from the
210             resource documentation's POD source code.
211             EOH
212             },
213              
214             # docu/text
215             'docu/text' =>
216             {
217             parent => 'docu',
218             handler => {
219             POST => 'handler_docu',
220             },
221             acl_profile => 'passerby',
222             cli => 'docu text $RESOURCE',
223             description => 'Display resource documentation in plain text',
224             documentation => <<'EOH',
225             =pod
226              
227             This resource provides access to on-line help documentation. It expects to find
228             a resource name (e.g. "employee/eid/:eid" including the double-quotes, and without
229             leading or trailing slash) in the request body. It returns a plain text rendering
230             of the POD source of the resource documentation.
231             EOH
232             },
233              
234             # echo
235             'echo' =>
236             {
237             parent => '/',
238             handler => {
239             POST => 'handler_echo',
240             },
241             acl_profile => 'admin',
242             cli => 'echo [$JSON]',
243             description => 'Echo the request body',
244             documentation => <<'EOH',
245             =pod
246              
247             This resource simply takes whatever content body was sent and echoes it
248             back in the response body.
249             EOH
250             },
251              
252             # forbidden
253             'forbidden' =>
254             {
255             parent => '/',
256             handler => 'handler_forbidden',
257             acl_profile => 'forbidden',
258             cli => 'forbidden',
259             description => 'A resource that is forbidden to all',
260             documentation => <<'EOH',
261             =pod
262              
263             This resource returns 403 Forbidden for all allowed methods, regardless of user.
264              
265             Implementation note: this can be accomplished for any resource by including an 'acl_profile'
266             property with the value 'undef' or any unrecognized privilege level string (like "foobar").
267             EOH
268             },
269              
270             # /holiday/:tsrange
271             'holiday/:tsrange' =>
272             {
273             parent => '/',
274             handler => {
275             'GET' => 'handler_holiday_tsrange',
276             },
277             acl_profile => 'passerby',
278             cli => 'handler $TSRANGE',
279             validations => {
280             'tsrange' => $tsrange_validation,
281             },
282             description => 'Determine holidays and weekends within a tsrange',
283             documentation => <<'EOH',
284             =pod
285              
286             Used with GET. For a given tsrange, return an object keyed on dates. The for
287             each date key is itself an object. If a date falls on a weekend, the value will
288             contain a subobject { "weekend": true }. If a date is a holiday, it will
289             contain a subobject { "holiday": true }. If a date is neither a weekend nor a
290             holiday, the value will be an empty object.
291             EOH
292             },
293              
294             # noop
295             'noop' =>
296             {
297             parent => '/',
298             handler => 'handler_noop',
299             acl_profile => 'passerby',
300             cli => 'noop',
301             description => 'A resource that does nothing',
302             documentation => <<'EOH',
303             =pod
304              
305             Regardless of anything, this resource does nothing at all.
306             EOH
307             },
308              
309             # param/:type/:param
310             'param/:type/:param' =>
311             {
312             parent => '/',
313             handler => {
314             'GET' => 'handler_param',
315             'PUT' => 'handler_param',
316             'DELETE' => 'handler_param',
317             },
318             acl_profile => 'admin',
319             cli => {
320             'GET' => 'param $TYPE $PARAM',
321             'PUT' => 'param $TYPE $PARAM $VALUE',
322             'DELETE' => 'param $TYPE $PARAM',
323             },
324             description => {
325             'GET' => 'Display value of a meta/core/site parameter',
326             'PUT' => 'Set value of a parameter (meta only)',
327             'DELETE' => 'Delete a parameter (meta only)',
328             },
329             documentation => <<'EOH',
330             =pod
331              
332             This resource can be used to look up (GET) meta, core, and site parameters,
333             as well as to set (PUT) and delete (DELETE) meta parameters.
334             EOH
335             validations => {
336             'type' => qr/^(meta)|(core)|(site)$/,
337             'param' => qr/^[[:alnum:]_][[:alnum:]_-]+$/,
338             },
339             },
340              
341             # session
342             'session' =>
343             {
344             parent => '/',
345             handler => {
346             GET => 'handler_session',
347             },
348             acl_profile => 'passerby',
349             cli => 'session',
350             description => 'Display the current session',
351             documentation => <<'EOH',
352             =pod
353              
354             Dumps the current session data (server-side).
355             EOH
356             },
357              
358             # session/terminate
359             'session/terminate' =>
360             {
361             parent => '/session',
362             handler => {
363             POST => 'handler_session_terminate',
364             },
365             acl_profile => 'passerby',
366             cli => 'session terminate',
367             description => 'Terminate the current session',
368             documentation => <<'EOH',
369             =pod
370              
371             Terminates the current session
372             EOH
373             },
374              
375             # version
376             'version' =>
377             {
378             parent => '/',
379             handler => {
380             GET => 'handler_version',
381             },
382             acl_profile => 'passerby',
383             cli => 'version',
384             description => 'Display application name and version',
385             documentation => <<'EOH',
386             =pod
387              
388             Shows the software version running on the present instance. The version displayed
389             is taken from the C<$VERSION> package variable of the package specified in the
390             C<MREST_APPLICATION_MODULE> site parameter.
391             EOH
392             },
393              
394             # /whoami
395             'whoami' => {
396             parent => '/',
397             handler => {
398             GET => 'handler_whoami',
399             },
400             acl_profile => 'passerby',
401             cli => 'whoami',
402             description => 'Display the current employee (i.e. the one we authenticated with)',
403             documentation => <<'EOH',
404             =pod
405              
406             Displays the profile of the currently logged-in employee
407             EOH
408             },
409              
410             };
411              
412             =head2 Activity resources
413              
414             =cut
415              
416             $defs->{'activity'} = {
417              
418             # /activity
419             'activity' =>
420             {
421             parent => '/',
422             handler => 'handler_noop',
423             acl_profile => 'passerby',
424             cli => 'activity',
425             description => 'Parent for activity resources',
426             documentation => <<'EOH',
427             =pod
428              
429             Parent for activity resources
430             EOH
431             },
432              
433             # /activity/aid
434             'activity/aid' =>
435             {
436             parent => 'activity',
437             handler => {
438             POST => 'handler_post_activity_aid',
439             },
440             acl_profile => 'admin',
441             cli => 'activity aid',
442             description => 'Update an existing activity object via POST request (AID must be included in request body)',
443             documentation => <<'EOH',
444             =pod
445              
446             Enables existing activity objects to be updated by sending a POST request to
447             the REST server. Along with the properties to be modified, the request body
448             must include an 'aid' property, the value of which specifies the AID to be
449             updated.
450             EOH
451             },
452              
453             # /activity/aid/:aid
454             'activity/aid/:aid' =>
455             {
456             parent => 'activity',
457             handler => {
458             GET => 'handler_activity_aid',
459             PUT => 'handler_activity_aid',
460             DELETE => 'handler_activity_aid',
461             },
462             acl_profile => {
463             GET => 'active',
464             PUT => 'admin',
465             DELETE => 'admin',
466             },
467             cli => 'activity aid $AID',
468             validations => {
469             'aid' => 'Int',
470             },
471             description => 'GET, PUT, or DELETE an activity object by its AID',
472             documentation => <<'EOH',
473             =pod
474              
475             This resource allows the user to GET, PUT, or DELETE an activity object by its
476             AID.
477              
478             =over
479              
480             =item * GET
481              
482             Retrieves an activity object by its AID.
483              
484             =item * PUT
485              
486             Updates the activity object whose AID is specified by the ':aid' URI parameter.
487             The fields to be updated and their new values should be sent in the request
488             body, e.g., like this:
489              
490             { "long_desc" : "new description", "disabled" : "f" }
491              
492             =item * DELETE
493              
494             Deletes the activity object whose AID is specified by the ':aid' URI parameter.
495             This will work only if nothing in the database refers to this activity.
496              
497             =back
498             EOH
499             },
500              
501             # /activity/all
502             'activity/all' =>
503             {
504             parent => 'activity',
505             handler => {
506             GET => 'handler_get_activity_all',
507             },
508             acl_profile => 'passerby',
509             cli => 'activity all',
510             description => 'Retrieve all activity objects (excluding disabled ones)',
511             documentation => <<'EOH',
512             =pod
513              
514             Retrieves all activity objects in the database (excluding disabled activities).
515             EOH
516             },
517              
518             # /activity/all/disabled
519             'activity/all/disabled' =>
520             {
521             parent => 'activity/all',
522             handler => {
523             GET => 'handler_get_activity_all_disabled',
524             },
525             acl_profile => 'admin',
526             cli => 'activity all disabled',
527             description => 'Retrieve all activity objects, including disabled ones',
528             documentation => <<'EOH',
529             =pod
530              
531             Retrieves all activity objects in the database (including disabled activities).
532             EOH
533             },
534              
535             # /activity/code
536             'activity/code' =>
537             {
538             parent => 'activity',
539             handler => {
540             POST => 'handler_post_activity_code',
541             },
542             acl_profile => 'admin',
543             cli => 'activity aid',
544             description => 'Update an existing activity object via POST request (activity code must be included in request body)',
545             documentation => <<'EOH',
546             =pod
547              
548             This resource enables existing activity objects to be updated, and new
549             activity objects to be inserted, by sending a POST request to the REST server.
550             Along with the properties to be modified/inserted, the request body must
551             include an 'code' property, the value of which specifies the activity to be
552             updated.
553             EOH
554             },
555              
556             # /activity/code/:code
557             'activity/code/:code' =>
558             {
559             parent => 'activity',
560             handler => {
561             GET => 'handler_get_activity_code',
562             PUT => 'handler_put_activity_code',
563             DELETE => 'handler_delete_activity_code',
564             },
565             acl_profile => {
566             GET => 'passerby',
567             PUT => 'admin',
568             DELETE => 'admin',
569             },
570             cli => 'activity code $CODE',
571             validations => {
572             'code' => qr/^[[:alnum:]_][[:alnum:]_-]+$/,
573             },
574             description => 'GET, PUT, or DELETE an activity object by its code',
575             documentation => <<'EOH',
576             =pod
577              
578             With this resource, a user can GET, PUT, or DELETE an activity object by its
579             code.
580              
581             =over
582              
583             =item * GET
584              
585             Retrieves an activity object by its code.
586              
587             =item * PUT
588              
589             Inserts new or updates existing activity object whose code is specified by the
590             ':code' URI parameter. The fields to be updated and their new values should be
591             sent in the request body, e.g., like this:
592              
593             { "long_desc" : "new description", "disabled" : "f" }
594              
595             =item * DELETE
596              
597             Deletes an activity object by its code whose code is specified by the ':code'
598             URI parameter. This will work only if nothing in the database refers to this
599             activity.
600              
601             =back
602             EOH
603             },
604              
605             };
606              
607              
608             =head2 Component resources
609              
610             =cut
611              
612             $defs->{'component'} = {
613              
614             # /component
615             'component' =>
616             {
617             parent => '/',
618             handler => 'handler_noop',
619             acl_profile => 'passerby',
620             cli => 'component',
621             description => 'Parent for component resources',
622             documentation => <<'EOH',
623             =pod
624              
625             Parent for component resources
626             EOH
627             },
628              
629             # /component/all
630             'component/all' =>
631             {
632             parent => 'component',
633             handler => {
634             GET => 'handler_get_component_all',
635             },
636             acl_profile => 'admin',
637             cli => 'component all',
638             description => 'Retrieve all component objects',
639             documentation => <<'EOH',
640             =pod
641              
642             Retrieves all component objects in the database.
643             EOH
644             },
645              
646             # /component/cid
647             'component/cid' =>
648             {
649             parent => 'component',
650             handler => {
651             POST => 'handler_post_component_cid',
652             },
653             acl_profile => 'admin',
654             cli => 'component cid',
655             description => 'Update an existing component object via POST request (cid must be included in request body)',
656             documentation => <<'EOH',
657             =pod
658              
659             Enables existing component objects to be updated by sending a POST request to
660             the REST server. Along with the properties to be modified, the request body
661             must include an 'cid' property, the value of which specifies the cid to be
662             updated.
663             EOH
664             },
665              
666             # /component/cid/:cid
667             'component/cid/:cid' =>
668             {
669             parent => 'component',
670             handler => {
671             GET => 'handler_component_cid',
672             PUT => 'handler_component_cid',
673             DELETE => 'handler_component_cid',
674             },
675             acl_profile => 'admin',
676             cli => 'component cid $cid',
677             validations => {
678             'cid' => 'Int',
679             },
680             description => 'GET, PUT, or DELETE an component object by its cid',
681             documentation => <<'EOH',
682             =pod
683              
684             This resource allows the user to GET, PUT, or DELETE an component object by its
685             cid.
686              
687             =over
688              
689             =item * GET
690              
691             Retrieves an component object by its cid.
692              
693             =item * PUT
694              
695             Updates the component object whose cid is specified by the ':cid' URI parameter.
696             The fields to be updated and their new values should be sent in the request
697             body, e.g., like this:
698              
699             { "path" : "new/path", "source" : "new source", "acl" : "inactive" }
700              
701             =item * DELETE
702              
703             Deletes the component object whose cid is specified by the ':cid' URI parameter.
704             This will work only if nothing in the database refers to this component.
705              
706             =back
707             EOH
708             },
709              
710             # /component/path
711             'component/path' =>
712             {
713             parent => 'component',
714             handler => {
715             POST => 'handler_post_component_path',
716             },
717             acl_profile => 'admin',
718             cli => 'component cid',
719             description => 'Update an existing component object via POST request (component path must be included in request body)',
720             documentation => <<'EOH',
721             =pod
722              
723             This resource enables existing component objects to be updated, and new
724             component objects to be inserted, by sending a POST request to the REST server.
725             Along with the properties to be modified/inserted, the request body must
726             include an 'path' property, the value of which specifies the component to be
727             updated.
728             EOH
729             },
730              
731             };
732              
733              
734             =head2 Employee resources
735              
736             =cut
737              
738             $defs->{'employee'} = {
739              
740             # /employee
741             'employee' =>
742             {
743             parent => '/',
744             handler => 'handler_noop',
745             acl_profile => 'passerby',
746             cli => 'employee',
747             description => 'Parent for employee resources',
748             documentation => <<'EOH',
749             =pod
750              
751             Parent for employee resources
752             EOH
753             },
754              
755             # /employee/count/?:priv
756             'employee/count/?:priv' =>
757             {
758             parent => 'employee',
759             handler => {
760             GET => 'handler_get_employee_count',
761             },
762             acl_profile => 'admin',
763             cli => 'employee count',
764             validations => {
765             'priv' => $priv_validation,
766             },
767             description => 'Display total count of employees (optionally by privlevel)',
768             documentation => <<'EOH',
769             =pod
770              
771             If ':priv' is not specified, gets the total number of employees in the
772             database. This includes employees of all privilege levels, including not only
773             administrators and active employees, but inactives and passerbies as well.
774              
775             If ':priv' is specified, gets the total number of employees with the
776             given privlevel. Valid privlevels are:
777              
778             =over
779              
780             =item * passerby
781              
782             =item * inactive
783              
784             =item * active
785              
786             =item * admin
787              
788             =back
789             EOH
790             },
791              
792             # /employee/eid
793             'employee/eid' =>
794             {
795             parent => 'employee',
796             handler => {
797             POST => 'handler_post_employee_eid',
798             },
799             acl_profile => 'inactive',
800             cli => 'employee eid $JSON',
801             description => 'Update existing employee (JSON request body with EID required)',
802             documentation => <<'EOH',
803             =pod
804              
805             This resource provides a way to update employee objects using the
806             POST method, provided the employee's EID is provided in the content body.
807             The properties to be modified should also be included, e.g.:
808              
809             { "eid" : 43, "fullname" : "Foo Bariful" }
810              
811             This would change the 'fullname' property of the employee with EID 43 to "Foo
812             Bariful" (provided such an employee exists).
813              
814             ACL note: 'inactive' and 'active' employees can use this resource to modify
815             their own employee profile. Exactly which fields can be updated may differ from
816             site to site (see the DOCHAZKA_PROFILE_EDITABLE_FIELDS site parameter).
817             EOH
818             },
819              
820             # /employee/eid/:eid
821             'employee/eid/:eid' =>
822             {
823             parent => 'employee',
824             handler => {
825             GET => 'handler_get_employee_eid',
826             PUT => 'handler_put_employee_eid',
827             DELETE => 'handler_delete_employee_eid',
828             },
829             acl_profile => {
830             GET => 'passerby',
831             PUT => 'inactive',
832             DELETE => 'admin',
833             },
834             cli => 'employee eid $EID [$JSON]',
835             validations => {
836             eid => 'Int',
837             },
838             description => 'GET: look up employee (exact match); PUT: update existing employee; DELETE: delete employee',
839             documentation => <<'EOH',
840             =pod
841              
842             With this resource, we can look up an employee by exact match (GET),
843             update an existing employee (PUT), or delete an employee (DELETE).
844              
845             =over
846              
847             =item * GET
848              
849             Retrieves an employee object by its EID.
850              
851             =item * PUT
852              
853             Updates the "employee profile" (employee object) of the employee with
854             the given EID. For example, if the request body was:
855              
856             { "fullname" : "Foo Bariful" }
857              
858             the request would change the 'fullname' property of the employee with EID 43
859             (provided such an employee exists) to "Foo Bariful". Any 'eid' property
860             provided in the content body will be ignored.
861              
862             ACL note: 'inactive' and 'active' employees can use this resource to modify
863             their own employee profile. Exactly which fields can be updated may differ from
864             site to site (see the DOCHAZKA_PROFILE_EDITABLE_FIELDS site parameter).
865              
866             =item * DELETE
867              
868             Deletes the employee with the given EID (will only work if the EID
869             exists and nothing in the database refers to it).
870              
871             =back
872             EOH
873             },
874              
875             # /employee/eid/:eid/full
876             'employee/eid/:eid/full' =>
877             {
878             parent => 'employee/eid/:eid',
879             handler => {
880             GET => 'handler_get_employee_eid_full',
881             },
882             acl_profile => 'active',
883             cli => 'employee eid $EID full',
884             validations => {
885             eid => 'Int',
886             },
887             description => 'Full employee profile',
888             documentation => <<'EOH',
889             =pod
890              
891             This resource enables any active employee to retrieve her own
892             full employee profile. Admins and supervisors can retrieve the
893             profiles of other employees.
894             EOH
895             },
896              
897             # /employee/eid/:eid/minimal
898             'employee/eid/:eid/minimal' =>
899             {
900             parent => 'employee/eid/:eid',
901             handler => {
902             GET => 'handler_get_employee_minimal',
903             },
904             acl_profile => 'passerby',
905             cli => 'employee eid $EID minimal',
906             validations => {
907             eid => 'Int',
908             },
909             description => 'List minimal info on an employee',
910             documentation => <<'EOH',
911             =pod
912              
913             This resource enables any employee to get minimal information
914             on any other employee. Useful for EID to nick conversion or to
915             look up another employee's email address or name.
916             EOH
917             },
918              
919             # /employee/eid/:eid/team
920             'employee/eid/:eid/team' =>
921             {
922             parent => 'employee/eid/:eid',
923             handler => {
924             GET => 'handler_get_employee_eid_team',
925             },
926             acl_profile => 'admin',
927             cli => 'employee eid $EID team',
928             validations => {
929             eid => 'Int',
930             },
931             description => 'List the nicks of an employee\'s team members',
932             documentation => <<'EOH',
933             =pod
934              
935             This resource enables administrators to list the nicks of team members
936             of an arbitrary employee - i.e. that employee\'s direct reports.
937             EOH
938             },
939              
940             # /employee/list/?:priv
941             'employee/list/?:priv' =>
942             {
943             parent => 'employee',
944             handler => {
945             GET => 'handler_get_employee_list',
946             },
947             acl_profile => 'admin',
948             cli => 'employee list [$PRIV]',
949             validations => {
950             'priv' => $priv_validation,
951             },
952             description => 'List nicks of employees',
953             documentation => <<'EOH',
954             =pod
955              
956             This resource enables the administrator to easily list the nicks of
957             employees. If priv is not given, all employees are listed.
958             EOH
959             },
960              
961             # /employee/nick
962             'employee/nick' =>
963             {
964             parent => 'employee',
965             handler => {
966             POST => 'handler_post_employee_nick',
967             },
968             acl_profile => 'inactive',
969             cli => 'employee nick $JSON',
970             description => 'Insert new/update existing employee (JSON request body with nick required)',
971             documentation => <<'EOH',
972             =pod
973              
974             This resource provides a way to insert/update employee objects using the
975             POST method, provided the employee's nick is provided in the content body.
976              
977             Consider, for example, the following request body:
978              
979             { "nick" : "foobar", "fullname" : "Foo Bariful" }
980              
981             If an employee "foobar" exists, such a request would change the 'fullname'
982             property of that employee to "Foo Bariful". On the other hand, if the employee
983             doesn't exist this HTTP request would cause a new employee 'foobar' to be
984             created.
985              
986             ACL note: 'inactive' and 'active' employees can use this resource to modify
987             their own employee profile. Exactly which fields can be updated may differ from
988             site to site (see the DOCHAZKA_PROFILE_EDITABLE_FIELDS site parameter).
989             EOH
990             },
991              
992             # /employee/nick/:nick
993             'employee/nick/:nick' =>
994             {
995             parent => 'employee',
996             handler => {
997             GET => 'handler_get_employee_nick',
998             PUT => 'handler_put_employee_nick',
999             DELETE => 'handler_delete_employee_nick',
1000             },
1001             acl_profile => {
1002             GET => 'passerby',
1003             PUT => 'inactive',
1004             DELETE => 'admin',
1005             },
1006             cli => 'employee nick $NICK [$JSON]',
1007             validations => {
1008             'nick' => $term_validation,
1009             },
1010             description => "Retrieves (GET), updates/inserts (PUT), and/or deletes (DELETE) the employee specified by the ':nick' parameter",
1011             documentation => <<'EOH',
1012             =pod
1013              
1014             Retrieves (GET), updates/inserts (PUT), and/or deletes (DELETE) the employee
1015             specified by the ':nick' parameter.
1016              
1017             =over
1018              
1019             =item * GET
1020              
1021             Retrieves employee object(s) by exact match. For example:
1022              
1023             GET employee/nick/foobar
1024              
1025             would look for an employee whose nick is 'foobar'.
1026              
1027             =item * PUT
1028              
1029             Inserts a new employee or updates an existing one (exact match only).
1030             If a 'nick' property is provided in the content body and its value is
1031             different from the nick provided in the URI, the employee's nick will be
1032             changed to the value provided in the content body.
1033              
1034             ACL note: 'inactive' and 'active' employees can use this resource to modify
1035             their own employee profile. Exactly which fields can be updated may differ from
1036             site to site (see the DOCHAZKA_PROFILE_EDITABLE_FIELDS site parameter).
1037              
1038             =item * DELETE
1039              
1040             Deletes an employee (exact match only). This will work only if the
1041             exact nick exists and nothing else in the database refers to the employee
1042             in question.
1043              
1044             =back
1045             EOH
1046             },
1047              
1048             # /employee/nick/:nick/ldap
1049             'employee/nick/:nick/ldap' =>
1050             {
1051             parent => 'employee/nick/:nick',
1052             handler => {
1053             GET => 'handler_get_employee_ldap',
1054             PUT => 'handler_put_employee_ldap',
1055             },
1056             acl_profile => {
1057             GET => 'passerby',
1058             PUT => 'active',
1059             },
1060             cli => 'employee nick $nick ldap',
1061             validations => {
1062             nick => $term_validation,
1063             },
1064             description => 'List LDAP info on an employee',
1065             documentation => <<'EOH',
1066             =pod
1067              
1068             LDAP search and sync resource
1069              
1070             =over
1071              
1072             =item * GET
1073              
1074             Enables any employee to perform an LDAP lookup on any other employee.
1075              
1076             =item * PUT
1077              
1078             Enables active employees to sync their own employee profile fields[1] from the
1079             site's LDAP database.
1080              
1081             Enables admin employees to sync/create[1] any existing employee from the LDAP
1082             database. If the employee does not exist, it will be created (just the employee
1083             object itself, without any privhistory records).
1084              
1085             =back
1086              
1087             [1] Which fields get synced depends on DOCHAZKA_LDAP_MAPPING site config
1088             parameter.
1089              
1090             EOH
1091             },
1092              
1093             # /employee/nick/:nick/full
1094             'employee/nick/:nick/full' =>
1095             {
1096             parent => 'employee/nick/:nick',
1097             handler => {
1098             GET => 'handler_get_employee_nick_full',
1099             },
1100             acl_profile => 'active',
1101             cli => 'employee nick $nick full',
1102             validations => {
1103             nick => $term_validation,
1104             },
1105             description => 'Full employee profile',
1106             documentation => <<'EOH',
1107             =pod
1108              
1109             This resource enables any active employee to retrieve her own
1110             full employee profile. Admins and supervisors can retrieve the
1111             profiles of other employees.
1112             EOH
1113             },
1114              
1115             # /employee/nick/:nick/minimal
1116             'employee/nick/:nick/minimal' =>
1117             {
1118             parent => 'employee/nick/:nick',
1119             handler => {
1120             GET => 'handler_get_employee_minimal',
1121             },
1122             acl_profile => 'passerby',
1123             cli => 'employee nick $nick minimal',
1124             validations => {
1125             nick => $term_validation,
1126             },
1127             description => 'List minimal info on an employee',
1128             documentation => <<'EOH',
1129             =pod
1130              
1131             This resource enables any employee to get minimal information
1132             on any other employee. Useful for nick to EID conversion or to
1133             look up another employee's email address or name.
1134             EOH
1135             },
1136              
1137             # /employee/nick/:nick/team
1138             'employee/nick/:nick/team' =>
1139             {
1140             parent => 'employee/nick/:nick',
1141             handler => {
1142             GET => 'handler_get_employee_nick_team',
1143             },
1144             acl_profile => 'admin',
1145             cli => 'employee nick $nick team',
1146             validations => {
1147             nick => $term_validation,
1148             },
1149             description => 'List the nicks of an employee\'s team members',
1150             documentation => <<'EOH',
1151             =pod
1152              
1153             This resource enables administrators to list the nicks of team members
1154             of an arbitrary employee - i.e. that employee\'s direct reports.
1155             EOH
1156             },
1157              
1158             # /employee/search
1159             'employee/search' =>
1160             {
1161             parent => 'employee',
1162             handler => 'handler_noop',
1163             acl_profile => 'passerby',
1164             cli => 'employee search',
1165             description => 'Employee search resources',
1166             documentation => <<'EOH',
1167             =pod
1168              
1169             See child resources.
1170             EOH
1171             },
1172              
1173             # /employee/search/nick/:key
1174             'employee/search/nick/:key' =>
1175             {
1176             parent => 'employee/search',
1177             handler => {
1178             'GET' => 'handler_get_employee_search_nick',
1179             },
1180             acl_profile => 'inactive',
1181             cli => 'employee search nick $KEY',
1182             description => 'Search employee profiles on nick (% is wild)',
1183             validations => {
1184             'key' => qr/^[%[:alnum:]_][%[:alnum:]_-]*$/,
1185             },
1186             documentation => <<'EOH',
1187             =pod
1188              
1189             Look up employee profiles using a search key, which can optionally contain
1190             a wildcard ('%'). For example:
1191              
1192             GET employee/search/nick/foo%
1193              
1194             would return a list of employees whose nick starts with 'foo', provided the '%'
1195             character in the URI is properly encoded (as '%25') by the client.
1196              
1197             Note that if the user provides no wildcard characters in the key, they will
1198             implicitly be added. Example: a search for 'foo' would be converted to
1199             '%foo%'. For a literal nick lookup, use the 'employee/nick/:nick' resource.
1200             EOH
1201             },
1202              
1203             # /employee/sec_id/:sec_id
1204             'employee/sec_id/:sec_id' =>
1205             {
1206             parent => 'employee',
1207             handler => {
1208             GET => 'handler_get_employee_sec_id',
1209             },
1210             acl_profile => {
1211             GET => 'passerby'
1212             },
1213             cli => 'employee sec_id $SEC_ID',
1214             description => 'GET an employee profile by the employee\'s secondary ID',
1215             validations => {
1216             'sec_id' => $term_validation,
1217             },
1218             documentation => <<'EOH',
1219             =pod
1220              
1221             Retrieves an employee object by the secondary ID (must be an exact match)
1222             EOH
1223             },
1224              
1225             # /employee/sec_id/:sec_id/minimal
1226             'employee/sec_id/:sec_id/minimal' =>
1227             {
1228             parent => 'employee/sec_id/:sec_id',
1229             handler => {
1230             GET => 'handler_get_employee_minimal',
1231             },
1232             acl_profile => 'passerby',
1233             cli => 'employee sec_id $sec_id minimal',
1234             validations => {
1235             'sec_id' => $term_validation,
1236             },
1237             description => 'List minimal info on an employee',
1238             documentation => <<'EOH',
1239             =pod
1240              
1241             This resource enables any employee to get minimal information
1242             on any other employee. Useful for sec_id to EID conversion or to
1243             look up another employee's email address or name.
1244             EOH
1245             },
1246              
1247             # /employee/self
1248             'employee/self' =>
1249             {
1250             parent => 'employee',
1251             handler => {
1252             GET => 'handler_whoami',
1253             POST => 'handler_post_employee_self',
1254             },
1255             acl_profile => {
1256             'GET' => 'passerby',
1257             'POST' => 'inactive',
1258             },
1259             cli => 'employee current',
1260             description => 'Retrieve (GET) and edit (POST) our own employee profile',
1261             documentation => <<'EOH',
1262             =pod
1263              
1264             With this resource, we can retrieve (GET) and/or edit (POST) our own employee
1265             profile.
1266              
1267             =over
1268              
1269             =item * GET
1270              
1271             Displays the profile of the currently logged-in employee. The information
1272             is limited to just the employee object itself.
1273              
1274             =item * POST
1275              
1276             Provides a way for an employee to update certain fields of her own employee
1277             profile. Exactly which fields can be updated may differ from site to site
1278             (see the DOCHAZKA_PROFILE_EDITABLE_FIELDS site parameter).
1279              
1280             =back
1281             EOH
1282             },
1283              
1284             # /employee/self/full
1285             'employee/self/full' =>
1286             {
1287             parent => 'employee/self',
1288             handler => {
1289             GET => 'handler_get_employee_self_full',
1290             },
1291             acl_profile => 'passerby',
1292             cli => 'employee current priv',
1293             description => 'Retrieve our own employee profile, privlevel, and schedule',
1294             documentation => <<'EOH',
1295             =pod
1296              
1297             Displays the "full profile" of the currently logged-in employee. The
1298             information includes the full employee object (taken from the 'current_emp'
1299             property) as well as the employee's current privlevel and schedule, which are
1300             looked up from the database.
1301              
1302             N.B. The value of the "schedule" property is just the SID, not the actual
1303             schedule record.
1304             EOH
1305             },
1306              
1307             # /employee/team
1308             'employee/team' =>
1309             {
1310             parent => 'employee',
1311             handler => {
1312             GET => 'handler_get_employee_team',
1313             },
1314             acl_profile => 'active',
1315             cli => 'team',
1316             description => 'List nicks of the logged-in employee\'s team members',
1317             documentation => <<'EOH',
1318             =pod
1319              
1320             This resource enables supervisors to easily list the nicks of
1321             employees in their team - i.e. their direct reports.
1322             EOH
1323             },
1324              
1325             };
1326              
1327              
1328             =head2 Genreport resources
1329              
1330             =cut
1331              
1332             $defs->{'genreport'} = {
1333              
1334             # /genreport
1335             'genreport' =>
1336             {
1337             parent => '/',
1338             handler => {
1339             GET => 'handler_noop',
1340             POST => 'handler_genreport',
1341             },
1342             acl_profile => {
1343             GET => 'passerby',
1344             POST => 'admin',
1345             },
1346             cli => 'genreport',
1347             description => 'Generate reports',
1348             documentation => <<'EOH',
1349             =pod
1350              
1351             The "POST genreport" resource generates reports from Mason templates.
1352             The resource takes a request body with one mandatory property, "path"
1353             (corresponding to the path of a Mason component relative to the component
1354             root), and one optional property, "parameters", which should be a hash
1355             of parameter names and values.
1356              
1357             The resource handler checks (1) if the component exists in the database,
1358             (2) whether current employee has sufficient permissions to generate the
1359             report (by comparing the employee's privlevel with the ACL profile of the
1360             component), and (3) validates the parameters, if any, by applying the
1361             validation rules specified in the component object. Iff all of these
1362             conditions are met, the component is called with the provided parameters.
1363             EOH
1364             },
1365              
1366             };
1367              
1368              
1369             =head2 History resources
1370              
1371             =cut
1372              
1373             $defs->{'history'} = {
1374              
1375             'priv/history' =>
1376             {
1377             parent => 'priv',
1378             handler => 'handler_noop',
1379             cli => 'priv history',
1380             description => 'Privilege history resources',
1381             documentation => <<'EOH',
1382             =pod
1383              
1384             This resource presents a list of subresources, all related to privilege histories.
1385             EOH
1386             },
1387              
1388             'schedule/history' =>
1389             {
1390             parent => 'schedule',
1391             handler => 'handler_noop',
1392             cli => 'schedule history',
1393             description => 'Schedule history resources',
1394             documentation => <<'EOH',
1395             =pod
1396              
1397             This resource presents a list of subresources, all related to schedule histories.
1398             EOH
1399             },
1400              
1401             'priv/history/eid/:eid' =>
1402             {
1403             parent => 'priv/history',
1404             handler => {
1405             GET => 'handler_history_get_multiple',
1406             POST => 'handler_history_post',
1407             },
1408             acl_profile => {
1409             GET => 'inactive',
1410             POST => 'admin',
1411             },
1412             cli => 'priv history eid $EID [$JSON]',
1413             validations => {
1414             'eid' => 'Int',
1415             },
1416             description => 'Retrieves entire history of privilege level changes for employee with the given EID (GET); or, with an appropriate content body, adds (POST) a record to employee\'s privhistory',
1417             documentation => <<'EOH',
1418             =pod
1419              
1420             Retrieves entire history of privilege level changes for employee with the given
1421             EID (GET); or, with an appropriate content body, adds (POST) a record to
1422             employee\'s privhistory.
1423              
1424             =over
1425              
1426             =item * GET
1427              
1428             Retrieves the "privhistory", or history of changes in
1429             privilege level, of the employee with the given EID.
1430              
1431             =item * POST
1432              
1433             Adds a record to the privhistory of the given employee. The content body should
1434             contain two properties: "effective" (a timestamp) and "priv" (one of
1435             "passerby", "inactive", "active", or "admin").
1436              
1437             It is assumed that schedule histories will be built up record-by-record;
1438             insertion of multiple history records in a single request is not supported.
1439              
1440             =back
1441              
1442             Update note: histories can be updated by adding new records and deleting old
1443             ones. Existing history records cannot be changed. Adds/deletes should be
1444             performed with due care - especially with regard to existing employee
1445             attendance data (if any).
1446             EOH
1447             },
1448              
1449             'schedule/history/eid/:eid' =>
1450             {
1451             parent => 'schedule/history',
1452             handler => {
1453             GET => 'handler_history_get_multiple',
1454             POST => 'handler_history_post',
1455             },
1456             acl_profile => {
1457             GET => 'inactive',
1458             POST => 'admin',
1459             },
1460             cli => 'schedule history eid $EID [$JSON]',
1461             validations => {
1462             'eid' => 'Int',
1463             },
1464             description => 'Retrieves entire history of schedule changes for employee with the given EID (GET); or, with an appropriate content body, adds (POST) a record to employee\'s schedule history',
1465             documentation => <<'EOH',
1466             =pod
1467              
1468             Retrieves entire history of schedule changes for employee with the given EID
1469             (GET); or, with an appropriate content body, adds (POST) a record to
1470             employee\'s schedule history.
1471              
1472             =over
1473              
1474             =item * GET
1475              
1476             Retrieves the full history of schedule changes of the employee with the given EID.
1477             For partial history, see 'schedule/history/eid/:eid/:tsrange'.
1478              
1479             =item * POST
1480              
1481             Adds a record to the schedule history of the given employee. The content body should
1482             contain two properties: "effective" (a timestamp) and "sid" (the ID of the schedule).
1483             Alternatively, an "scode" property (schedule code) can be sent instead of "sid".
1484              
1485             It is assumed that schedule histories will be built up record-by-record;
1486             insertion of multiple history records in a single request is not supported.
1487              
1488             =back
1489              
1490             Update note: histories can be updated by adding new records and deleting old
1491             ones. Existing history records cannot be changed. Adds/deletes should be
1492             performed with due care - especially with regard to existing employee
1493             attendance data (if any).
1494             EOH
1495             },
1496              
1497             'priv/history/eid/:eid/:tsrange' =>
1498             {
1499             parent => 'priv/history',
1500             handler => {
1501             GET => 'handler_history_get_multiple',
1502             },
1503             acl_profile => 'inactive',
1504             cli => 'priv history eid $EID $TSRANGE',
1505             description => 'Get a slice of history of privilege level changes for employee with the given EID',
1506             validations => {
1507             'eid' => 'Int',
1508             'tsrange' => $tsrange_validation,
1509             },
1510             documentation => <<'EOH',
1511             =pod
1512              
1513             Retrieves a slice (given by the tsrange argument) of the employee's
1514             "privhistory" (history of changes in privilege level).
1515             EOH
1516             },
1517              
1518             'schedule/history/eid/:eid/:tsrange' =>
1519             {
1520             parent => 'schedule/history',
1521             handler => {
1522             GET => 'handler_history_get_multiple',
1523             },
1524             acl_profile => 'inactive',
1525             cli => 'schedule history eid $EID $TSRANGE',
1526             description => 'Get a slice of history of schedule changes for employee with the given EID',
1527             validations => {
1528             'eid' => 'Int',
1529             'tsrange' => $tsrange_validation,
1530             },
1531             documentation => <<'EOH',
1532             =pod
1533              
1534             Retrieves a slice (given by the tsrange argument) of the employee's
1535             "schedule history" (history of changes in schedule).
1536             EOH
1537             },
1538              
1539             'priv/history/eid/:eid/:ts' =>
1540             {
1541             parent => 'priv/history',
1542             handler => {
1543             GET => 'handler_history_get_single',
1544             },
1545             acl_profile => 'inactive',
1546             cli => 'priv history eid $EID $TS',
1547             description => 'Get the privhistory record effective at a given timestamp',
1548             validations => {
1549             'eid' => 'Int',
1550             'ts' => $ts_validation,
1551             },
1552             documentation => <<'EOH',
1553             =pod
1554              
1555             Retrieves an employee's effective privhistory record (status change) as of a
1556             given timestamp.
1557             EOH
1558             },
1559              
1560             'schedule/history/eid/:eid/:ts' =>
1561             {
1562             parent => 'schedule/history',
1563             handler => {
1564             GET => 'handler_history_get_single',
1565             },
1566             acl_profile => 'inactive',
1567             cli => 'schedule history eid $EID $TS',
1568             description => 'Get the privhistory record effective at a given timestamp',
1569             validations => {
1570             'eid' => 'Int',
1571             'ts' => $ts_validation,
1572             },
1573             documentation => <<'EOH',
1574             =pod
1575              
1576             Retrieves an employee's effective schedhistory record (status change) as of a
1577             given timestamp.
1578             EOH
1579             },
1580              
1581             'priv/history/eid/:eid/now' =>
1582             {
1583             parent => 'priv/history',
1584             handler => {
1585             GET => 'handler_history_get_single',
1586             },
1587             acl_profile => 'inactive',
1588             cli => 'priv history eid $EID now',
1589             description => 'Get the privhistory record effective as of "now" (the current timestamp)',
1590             validations => {
1591             'eid' => 'Int',
1592             },
1593             documentation => <<'EOH',
1594             =pod
1595              
1596             Retrieves an employee's effective privhistory record (status change) as of
1597             "now" (the current timestamp).
1598             EOH
1599             },
1600              
1601             'schedule/history/eid/:eid/now' =>
1602             {
1603             parent => 'schedule/history',
1604             handler => {
1605             GET => 'handler_history_get_single',
1606             },
1607             acl_profile => 'inactive',
1608             cli => 'schedule history eid $EID now',
1609             description => 'Get the privhistory record effective as of "now" (the current timestamp)',
1610             validations => {
1611             'eid' => 'Int',
1612             },
1613             documentation => <<'EOH',
1614             =pod
1615              
1616             Retrieves an employee's effective schedhistory record (status change) as of
1617             "now" (the current timestamp).
1618             EOH
1619             },
1620              
1621             'priv/history/nick/:nick' =>
1622             {
1623             parent => 'priv/history',
1624             handler => {
1625             GET => 'handler_history_get_multiple',
1626             POST => 'handler_history_post',
1627             },
1628             acl_profile => {
1629             GET => 'inactive',
1630             POST => 'admin',
1631             },
1632             cli => 'priv history nick $NICK [$JSON]',
1633             validations => {
1634             'nick' => $term_validation,
1635             },
1636             description => 'Retrieves entire history of privilege level changes for employee with the given nick (GET); or, with an appropriate content body, adds (PUT) a record to employee\'s privhistory',
1637             documentation => <<'EOH',
1638             =pod
1639              
1640             Retrieves entire history of privilege level changes for employee with the given
1641             nick (GET); or, with an appropriate content body, adds (PUT) a record to
1642             employee\'s privhistory.
1643              
1644             =over
1645              
1646             =item * GET
1647              
1648             Retrieves the "privhistory", or history of changes in
1649             privilege level, of the employee with the given nick.
1650              
1651             =item * POST
1652              
1653             Adds a record to the privhistory of the given employee. The content body should
1654             contain two properties: "effective" (a timestamp) and "priv" (one of
1655             "passerby", "inactive", "active", or "admin").
1656              
1657             It is assumed that schedule histories will be built up record-by-record;
1658             insertion of multiple history records in a single request is not supported.
1659              
1660             =back
1661              
1662             Update note: histories can be updated by adding new records and deleting old
1663             ones. Existing history records cannot be changed. Adds/deletes should be
1664             performed with due care - especially with regard to existing employee
1665             attendance data (if any).
1666             EOH
1667             },
1668              
1669             'schedule/history/nick/:nick' =>
1670             {
1671             parent => 'schedule/history',
1672             handler => {
1673             GET => 'handler_history_get_multiple',
1674             POST => 'handler_history_post',
1675             },
1676             acl_profile => {
1677             GET => 'inactive',
1678             POST => 'admin',
1679             },
1680             cli => 'schedule history nick $NICK [$JSON]',
1681             validations => {
1682             'nick' => $term_validation,
1683             },
1684             description => 'Retrieves entire history of schedule changes for employee with the given nick (GET); or, with an appropriate content body, adds (PUT) a record to employee\'s schedule history',
1685             documentation => <<'EOH',
1686             =pod
1687              
1688             Retrieves entire history of schedule changes for employee with the given nick
1689             (GET); or, with an appropriate content body, adds (PUT) a record to employee\'s
1690             schedule history.
1691            
1692             =over
1693              
1694             =item * GET
1695              
1696             Retrieves the full history of schedule changes of the employee with the given nick.
1697             For partial histories, see 'schedule/history/nick/:nick/:tsrange'.
1698              
1699             =item * POST
1700              
1701             Adds a record to the schedule history of the given employee. The content body should
1702             contain two properties: "effective" (a timestamp) and "sid" (the ID of the schedule).
1703             Alternatively, an "scode" property (schedule code) can be sent instead of "sid".
1704              
1705             It is assumed that schedule histories will be built up record-by-record;
1706             insertion of multiple history records in a single request is not supported.
1707              
1708             =back
1709              
1710             Update note: histories can be updated by adding new records and deleting old
1711             ones. Existing history records cannot be changed. Adds/deletes should be
1712             performed with due care - especially with regard to existing employee
1713             attendance data (if any).
1714             EOH
1715             },
1716              
1717             'priv/history/nick/:nick/:tsrange' =>
1718             {
1719             parent => 'priv/history',
1720             handler => {
1721             GET => 'handler_history_get_multiple',
1722             },
1723             acl_profile => 'inactive',
1724             cli => 'priv history nick $NICK $TSRANGE',
1725             validations => {
1726             'nick' => $term_validation,
1727             'tsrange' => $tsrange_validation,
1728             },
1729             description => 'Get partial history of privilege level changes for employee with the given nick ' .
1730             '(i.e, limit to given tsrange)',
1731             documentation => <<'EOH',
1732             =pod
1733              
1734             Retrieves a slice (given by the tsrange argument) of the employee's
1735             "privhistory" (history of changes in privilege level).
1736             EOH
1737             },
1738              
1739             'schedule/history/nick/:nick/:tsrange' =>
1740             {
1741             parent => 'schedule/history',
1742             handler => {
1743             GET => 'handler_history_get_multiple',
1744             },
1745             acl_profile => 'inactive',
1746             cli => 'schedule history nick $NICK $TSRANGE',
1747             validations => {
1748             'nick' => $term_validation,
1749             'tsrange' => $tsrange_validation,
1750             },
1751             description => 'Get partial history of schedule changes for employee with the given nick ' .
1752             '(i.e, limit to given tsrange)',
1753             documentation => <<'EOH',
1754             =pod
1755              
1756             Retrieves a slice (given by the tsrange argument) of the employee's
1757             "schedule history" (history of changes in schedule).
1758             EOH
1759             },
1760              
1761             'priv/history/phid/:phid' =>
1762             {
1763             parent => 'priv/history',
1764             handler => {
1765             GET => 'handler_history_get_phid',
1766             POST => 'handler_history_post_phid',
1767             DELETE => 'handler_history_delete_phid',
1768             },
1769             acl_profile => 'admin',
1770             cli => 'priv history phid $PHID',
1771             validations => {
1772             'phid' => 'Int',
1773             },
1774             description => 'Retrieves (GET), updates (POST), or deletes (DELETE) a single privilege history record by its PHID',
1775             documentation => <<'EOH',
1776             =pod
1777              
1778             Retrieves (GET), updates (POST), or deletes (DELETE) a single privilege history record by its
1779             PHID.
1780              
1781             =over
1782              
1783             =item * GET
1784              
1785             Retrieves a privhistory record by its PHID.
1786              
1787             =item * POST
1788              
1789             Updates a privilege history record by its PHID. The 'phid' and 'eid'
1790             properties cannot be changed in this way.
1791              
1792             =item * DELETE
1793              
1794             Deletes a privhistory record by its PHID.
1795              
1796             =back
1797              
1798             (N.B.: history records can be added using POST requests on "priv/history/eid/:eid" or
1799             "priv/history/nick/:nick")
1800             EOH
1801             },
1802              
1803             'schedule/history/shid/:shid' =>
1804             {
1805             parent => 'schedule/history',
1806             handler => {
1807             GET => 'handler_history_get_shid',
1808             POST => 'handler_history_post_shid',
1809             DELETE => 'handler_history_delete_shid',
1810             },
1811             acl_profile => 'admin',
1812             cli => 'schedule history phid $PHID',
1813             validations => {
1814             'shid' => 'Int',
1815             },
1816             description => 'Retrieves (GET), updates (POST), or deletes (DELETE) a single schedule history record by its SHID',
1817             documentation => <<'EOH',
1818             =pod
1819              
1820             Retrieves (GET), updates (POST), or deletes (DELETE) a single schedule
1821             history record by its SHID.
1822              
1823             =over
1824              
1825             =item * GET
1826              
1827             Retrieves a schedule history record by its SHID.
1828              
1829             =item * POST
1830              
1831             Updates a schedule history record by its SHID. The 'shid' and 'eid'
1832             properties cannot be changed in this way.
1833              
1834             =item * DELETE
1835              
1836             Deletes a schedule history record by its SHID.
1837              
1838             =back
1839              
1840             (N.B.: history records can be added using POST requests on "schedule/history/eid/:eid" or
1841             "schedule/history/nick/:nick")
1842             EOH
1843             },
1844              
1845             'priv/history/self/?:tsrange' =>
1846             {
1847             parent => 'priv/history',
1848             handler => {
1849             GET => 'handler_history_self',
1850             },
1851             acl_profile => 'inactive',
1852             cli => 'priv history self [$TSRANGE]',
1853             validations => {
1854             'tsrange' => $tsrange_validation,
1855             },
1856             description => 'Retrieves privhistory of present employee, with option to limit to :tsrange',
1857             documentation => <<'EOH',
1858             =pod
1859              
1860             This resource retrieves the "privhistory", or history of changes in
1861             privilege level, of the present employee. Optionally, the listing can be
1862             limited to a specific tsrange such as
1863              
1864             "[2014-01-01, 2014-12-31)"
1865              
1866             EOH
1867             },
1868              
1869             'schedule/history/self/?:tsrange' =>
1870             {
1871             parent => 'schedule/history',
1872             handler => {
1873             GET => 'handler_history_self',
1874             },
1875             acl_profile => 'inactive',
1876             cli => 'schedule history self [$TSRANGE]',
1877             validations => {
1878             'tsrange' => $tsrange_validation,
1879             },
1880             description => 'Retrieves schedule history of present employee, with option to limit to :tsrange',
1881             documentation => <<'EOH',
1882             =pod
1883              
1884             This resource retrieves the "schedule history", or history of changes in
1885             schedule, of the present employee. Optionally, the listing can be
1886             limited to a specific tsrange such as
1887              
1888             "[2014-01-01, 2014-12-31)"
1889              
1890             EOH
1891             },
1892              
1893             };
1894              
1895              
1896             =head2 Interval resources
1897              
1898             =cut
1899              
1900             $defs->{'interval'} = {
1901              
1902             # /interval
1903             'interval' =>
1904             {
1905             parent => '/',
1906             handler => 'handler_noop',
1907             acl_profile => 'passerby',
1908             cli => 'interval',
1909             description => 'Parent for interval resources',
1910             documentation => <<'EOH',
1911             =pod
1912              
1913             Parent for interval resources
1914             EOH
1915             },
1916              
1917             # /interval/eid/:eid/:tsrange
1918             'interval/eid/:eid/:tsrange' =>
1919             {
1920             parent => 'interval',
1921             handler => {
1922             GET => 'handler_interval_eid',
1923             DELETE => 'handler_interval_eid',
1924             },
1925             acl_profile => 'active',
1926             cli => 'interval eid $EID $TSRANGE',
1927             validations => {
1928             'eid' => 'Int',
1929             'tsrange' => $tsrange_validation,
1930             },
1931             description => 'Retrieve an arbitrary employee\'s intervals over the given tsrange',
1932             documentation => <<'EOH',
1933             =pod
1934              
1935             With this resource, administrators can retrieve any employee's intervals
1936             over a given tsrange, and active employees can do the same with their own intervals.
1937              
1938             Before any records are returned, the tsrange is checked to see if it overlaps with
1939             any privlevel or schedule changes - in which case an error is returned. This is so
1940             interval report-generators do not have to handle changes in employee status.
1941              
1942             By default, the number of intervals returned is limited to 500. This number
1943             can be changed via the DOCHAZKA_INTERVAL_SELECT_LIMIT site configuration
1944             parameter (set to 'undef' for no limit).
1945             EOH
1946             },
1947              
1948             # /interval/eid/:eid/:ts/:psqlint'
1949             'interval/eid/:eid/:ts/:psqlint' =>
1950             {
1951             parent => 'interval',
1952             handler => {
1953             GET => 'handler_interval_eid',
1954             DELETE => 'handler_interval_eid',
1955             },
1956             acl_profile => 'active',
1957             cli => 'interval eid $EID $TS DELTA $PSQLINT',
1958             validations => {
1959             'eid' => 'Int',
1960             'ts' => $ts_validation,
1961             'psqlint' => $psqlint_validation,
1962             },
1963             description => 'Retrieve an arbitrary employee\'s intervals falling within a time period',
1964             documentation => <<'EOH',
1965             =pod
1966              
1967             This is just like 'interval/eid/:eid/:tsrange' except that the time range is
1968             specified by giving a timestamp and a PostgreSQL time interval, e.g "1 week 3 days".
1969             EOH
1970             },
1971              
1972             # /interval/fillup
1973             'interval/fillup' =>
1974             {
1975             parent => 'interval',
1976             handler => {
1977             POST => 'handler_interval_fillup',
1978             },
1979             acl_profile => {
1980             POST => 'active',
1981             },
1982             cli => 'interval fillup',
1983             description => 'Generate intervals according to schedule',
1984             documentation => <<'EOH',
1985             =pod
1986              
1987             Used with POST to create multiple attendance intervals for an employee,
1988             according to the prevailing schedule.
1989              
1990             The request body is a JSON object with the following parameters:
1991              
1992             =over
1993              
1994             =item * C<eid> (the EID of the employee to create intervals for; alternatively, C<nick> or C<sec_id>)
1995              
1996             =item * C<tsrange> (the time span over which to create intervals)
1997              
1998             =item * C<datelist> (a list of dates to create intervals for)
1999              
2000             =item * C<dry_run> (boolean value)
2001              
2002             =item * C<aid> (the AID of the activity; alternatively, C<code>)
2003              
2004             =item * C<desc> (optional interval description)
2005              
2006             =item * C<remark> (optional remark)
2007              
2008             =back
2009              
2010             If C<tsrange> is provided, C<datelist> should be omitted - and vice versa.
2011              
2012             If C<dry_run> is true, the resource does not change the database state.
2013             EOH
2014             },
2015              
2016             # /interval/iid
2017             'interval/iid' =>
2018             {
2019             parent => 'interval',
2020             handler => {
2021             POST => 'handler_post_interval_iid',
2022             },
2023             acl_profile => 'active',
2024             cli => 'interval iid $JSON',
2025             description => 'Update an existing interval object via POST request (iid must be included in request body)',
2026             documentation => <<'EOH',
2027             =pod
2028              
2029             Enables existing interval objects to be updated by sending a POST request to
2030             the REST server. Along with the properties to be modified, the request body
2031             must include an 'iid' property, the value of which specifies the iid to be
2032             updated.
2033             EOH
2034             },
2035              
2036             # /interval/iid/:iid
2037             'interval/iid/:iid' =>
2038             {
2039             parent => 'interval',
2040             handler => {
2041             GET => 'handler_get_interval_iid',
2042             PUT => 'handler_interval_iid',
2043             DELETE => 'handler_interval_iid',
2044             },
2045             acl_profile => 'active',
2046             cli => 'interval iid $iid [$JSON]',
2047             validations => {
2048             'iid' => 'Int',
2049             },
2050             description => 'GET, PUT, or DELETE an interval object by its iid',
2051             documentation => <<'EOH',
2052             =pod
2053              
2054             This resource makes it possible to GET, PUT, or DELETE an interval object by
2055             its IID.
2056              
2057             =over
2058              
2059             =item * GET
2060              
2061             Retrieves an interval object by its IID.
2062              
2063             =item * PUT
2064              
2065             Updates the interval object whose iid is specified by the ':iid' URI parameter.
2066             The fields to be updated and their new values should be sent in the request
2067             body, e.g., like this:
2068              
2069             {
2070             "eid" : 34,
2071             "aid" : 1,
2072             "intvl" : '[ 2014-11-18 08:00, 2014-11-18 12:00 )'
2073             }
2074              
2075             =item * DELETE
2076              
2077             Deletes the interval object whose iid is specified by the ':iid' URI parameter.
2078             As long as the interval does not overlap with a lock interval, the delete operation
2079             will probably work as expected.
2080              
2081             =back
2082              
2083             ACL note: 'active' employees can update/delete only their own unlocked intervals.
2084             EOH
2085             },
2086              
2087             # /interval/new
2088             'interval/new' =>
2089             {
2090             parent => 'interval',
2091             handler => {
2092             POST => 'handler_interval_new',
2093             },
2094             acl_profile => 'active',
2095             cli => 'interval new $JSON',
2096             description => 'Add a new attendance data interval',
2097             documentation => <<'EOH',
2098             =pod
2099              
2100             This is the resource by which employees add new attendance data to the
2101             database. It takes a request body containing, at the very least, C<aid> and
2102             C<intvl> properties. Additionally, it can contain C<long_desc>, while
2103             administrators can also specify C<eid> and C<remark>.
2104             EOH
2105             },
2106              
2107             # /interval/nick/:nick/:tsrange
2108             'interval/nick/:nick/:tsrange' =>
2109             {
2110             parent => 'interval',
2111             handler => {
2112             GET => 'handler_interval_nick',
2113             DELETE => 'handler_interval_nick',
2114             },
2115             acl_profile => 'active',
2116             cli => 'interval nick $NICK $TSRANGE',
2117             validations => {
2118             'nick' => $term_validation,
2119             'tsrange' => $tsrange_validation,
2120             },
2121             description => 'Retrieve an arbitrary employee\'s intervals over the given tsrange',
2122             documentation => <<'EOH',
2123             =pod
2124              
2125             With this resource, administrators can retrieve any employee's intervals
2126             over a given tsrange, and active employees can do the same with their own intervals.
2127              
2128             Before any records are returned, the tsrange is checked to see if it overlaps with
2129             any privlevel or schedule changes - in which case an error is returned. This is so
2130             interval report-generators do not have to handle changes in employee status.
2131              
2132             By default, the number of intervals returned is limited to 500. This number
2133             can be changed via the DOCHAZKA_INTERVAL_SELECT_LIMIT site configuration
2134             parameter (set to 'undef' for no limit).
2135             EOH
2136             },
2137              
2138             # /interval/nick/:nick/:ts/:psqlint'
2139             'interval/nick/:nick/:ts/:psqlint' =>
2140             {
2141             parent => 'interval',
2142             handler => {
2143             GET => 'handler_interval_nick',
2144             DELETE => 'handler_interval_nick',
2145             },
2146             acl_profile => 'active',
2147             cli => 'interval nick $NICK $TS DELTA $PSQLINT',
2148             validations => {
2149             'nick' => $term_validation,
2150             'ts' => $ts_validation,
2151             'psqlint' => $psqlint_validation,
2152             },
2153             description => 'Retrieve an arbitrary employee\'s intervals falling within a time period',
2154             documentation => <<'EOH',
2155             =pod
2156              
2157             This is just like 'interval/nick/:nick/:tsrange' except that the time range is
2158             specified by giving a timestamp and a PostgreSQL time interval, e.g "1 week 3 days".
2159             EOH
2160             },
2161              
2162             # /interval/scheduled
2163             'interval/scheduled' =>
2164             {
2165             parent => 'interval',
2166             handler => {
2167             POST => 'handler_interval_scheduled',
2168             },
2169             acl_profile => {
2170             POST => 'active',
2171             },
2172             cli => 'interval scheduled',
2173             description => 'Generate intervals according to schedule',
2174             documentation => <<'EOH',
2175             =pod
2176              
2177             Used with POST to generate intervals according to an employee's schedule,
2178             without actually creating any intervals - for example, to find out what
2179             intervals are scheduled for a given day.
2180              
2181             (This resource is very similar to C<interval/fillup>. The key difference is it
2182             does not check for existing attendance intervals that might conflict. As a
2183             result, it can easily produce conflicts if used with C<<dry_run => 0>> (false).
2184             If you want a list of non-conflicting intervals, use C<interval/fillup> with
2185             C<<dry_run => 1>> (true).)
2186              
2187             The request body takes the following parameters:
2188              
2189             =over
2190              
2191             =item * C<eid> (the EID of the employee to create intervals for; alternatively, C<nick> or C<sec_id>)
2192              
2193             =item * C<tsrange> (the time span over which to create intervals)
2194              
2195             =item * C<datelist> (a list of dates to create intervals for)
2196              
2197             =back
2198              
2199             If C<tsrange> is provided, C<datelist> should be omitted - and vice versa.
2200              
2201             EOH
2202             },
2203              
2204             # /interval/self/:tsrange
2205             'interval/self/:tsrange' =>
2206             {
2207             parent => 'interval',
2208             handler => {
2209             GET => 'handler_interval_self',
2210             DELETE => 'handler_interval_self',
2211             },
2212             acl_profile => 'inactive',
2213             cli => 'interval self $TSRANGE',
2214             validations => {
2215             'tsrange' => $tsrange_validation,
2216             },
2217             description => 'Retrieve one\'s own intervals over the given tsrange',
2218             documentation => <<'EOH',
2219             =pod
2220              
2221             With this resource, employees can retrieve their own attendance intervals
2222             over a given tsrange.
2223              
2224             Before any records are returned, the tsrange is checked to see if it overlaps with
2225             any privlevel or schedule changes - in which case an error is returned. This is so
2226             interval report-generators do not have to handle changes in employee status.
2227              
2228             By default, the number of intervals returned is limited to 500. This number
2229             can be changed via the DOCHAZKA_INTERVAL_SELECT_LIMIT site configuration
2230             parameter (set to 'undef' for no limit).
2231             EOH
2232             },
2233              
2234             # /interval/self/:ts/:psqlint'
2235             'interval/:self/:ts/:psqlint' =>
2236             {
2237             parent => 'interval',
2238             handler => {
2239             GET => 'handler_interval_self',
2240             DELETE => 'handler_interval_self',
2241             },
2242             acl_profile => 'active',
2243             cli => 'INTERVAL SELF $TS DELTA $PSQLINT',
2244             validations => {
2245             'ts' => $ts_validation,
2246             'psqlint' => $psqlint_validation,
2247             },
2248             description => 'Retrieve one\'s own intervals falling within a time period',
2249             documentation => <<'EOH',
2250             =pod
2251              
2252             This is just like 'interval/self/:tsrange' except that the time range is
2253             specified by giving a timestamp and a PostgreSQL time interval, e.g "1 week 3 days".
2254             EOH
2255             },
2256              
2257             # /interval/summary/eid/:eid/:tsrange
2258             'interval/summary/eid/:eid/:tsrange' => {
2259             parent => 'interval',
2260             handler => {
2261             GET => 'handler_get_interval_summary',
2262             },
2263             acl_profile => 'inactive',
2264             cli => 'interval summary',
2265             description => 'Retrieve summary of an employee\'s intervals over a time period',
2266             documentation => <<'EOH',
2267             =pod
2268              
2269             With this resource, employees can generate summaries of their attendance intervals
2270             over a given period.
2271              
2272             EOH
2273             },
2274              
2275             };
2276              
2277              
2278             =head2 Lock resources
2279              
2280             =cut
2281              
2282             $defs->{'lock'} = {
2283              
2284             # /lock
2285             'lock' =>
2286             {
2287             parent => '/',
2288             handler => 'handler_noop',
2289             acl_profile => 'passerby',
2290             cli => 'lock',
2291             description => 'Parent for lock resources',
2292             documentation => <<'EOH',
2293             =pod
2294              
2295             Parent for lock resources
2296             EOH
2297             },
2298              
2299             # /lock/eid/:eid/:tsrange
2300             'lock/eid/:eid/:tsrange' =>
2301             {
2302             parent => 'lock',
2303             handler => {
2304             GET => 'handler_get_lock_eid',
2305             },
2306             acl_profile => 'active',
2307             cli => 'lock eid $EID $TSRANGE',
2308             validations => {
2309             'eid' => 'Int',
2310             'tsrange' => $tsrange_validation,
2311             },
2312             description => 'Retrieve an arbitrary employee\'s locks over the given tsrange',
2313             documentation => <<'EOH',
2314             =pod
2315              
2316             With this resource, administrators can retrieve any employee's locks
2317             over a given tsrange.
2318              
2319             There are no syntactical limitations on the tsrange, but if too many records would
2320             be fetched, the return status will be C<DISPATCH_TOO_MANY_RECORDS_FOUND>.
2321             EOH
2322             },
2323              
2324             # /lock/lid
2325             'lock/lid' =>
2326             {
2327             parent => 'lock',
2328             handler => {
2329             POST => 'handler_post_lock_lid',
2330             },
2331             acl_profile => 'admin',
2332             cli => 'lock lid $JSON',
2333             description => 'Update an existing lock object via POST request (lid must be included in request body)',
2334             documentation => <<'EOH',
2335             =pod
2336              
2337             Enables existing lock objects to be updated by sending a POST request to
2338             the REST server. Along with the properties to be modified, the request body
2339             must include an 'lid' property, the value of which specifies the lid to be
2340             updated.
2341             EOH
2342             },
2343              
2344             # /lock/lid/:lid
2345             'lock/lid/:lid' =>
2346             {
2347             parent => 'lock',
2348             handler => {
2349             GET => 'handler_get_lock_lid',
2350             PUT => 'handler_lock_lid',
2351             DELETE => 'handler_lock_lid',
2352             },
2353             acl_profile => {
2354             GET => 'active',
2355             PUT => 'admin',
2356             DELETE => 'admin',
2357             },
2358             cli => 'lock lid $lid [$JSON]',
2359             validations => {
2360             'lid' => 'Int',
2361             },
2362             description => 'GET, PUT, or DELETE an lock object by its LID',
2363             documentation => <<'EOH',
2364             =pod
2365              
2366             This resource makes it possible to GET, PUT, or DELETE an lock object by its
2367             LID.
2368              
2369             =over
2370              
2371             =item * GET
2372              
2373             Retrieves an lock object by its lid.
2374              
2375             =item * PUT
2376              
2377             Updates the lock object whose lid is specified by the ':lid' URI parameter.
2378             The fields to be updated and their new values should be sent in the request
2379             body, e.g., like this:
2380              
2381             {
2382             "eid" : 34,
2383             "intvl" : '[ 2014-11-18 00:00, 2014-11-18 24:00 )'
2384             }
2385              
2386             =item * DELETE
2387              
2388             Deletes the lock object whose lid is specified by the ':lid' URI parameter.
2389              
2390             =back
2391              
2392             ACL note: 'active' employees can view only their own locks, and of course
2393             admin privilege is required to modify or remove a lock.
2394             EOH
2395             },
2396             # /lock/new
2397             'lock/new' =>
2398             {
2399             parent => 'lock',
2400             handler => {
2401             POST => 'handler_lock_new',
2402             },
2403             acl_profile => 'active',
2404             cli => 'lock new $JSON',
2405             description => 'Add a new attendance data lock',
2406             documentation => <<'EOH',
2407             =pod
2408              
2409             This is the resource by which the attendance data entered by an employee
2410             for a given time period can be "locked" to prevent any subsequent
2411             modifications. It takes a request body containing, at the very least, an
2412             C<intvl> property specifying the tsrange to lock. Additionally, administrators
2413             can specify C<remark> and C<eid> properties.
2414             EOH
2415             },
2416              
2417             # /lock/nick/:nick/:tsrange
2418             'lock/nick/:nick/:tsrange' =>
2419             {
2420             parent => 'lock',
2421             handler => {
2422             GET => 'handler_get_lock_nick',
2423             },
2424             acl_profile => 'active',
2425             cli => 'lock nick $NICK $TSRANGE',
2426             validations => {
2427             'nick' => $term_validation,
2428             'tsrange' => $tsrange_validation,
2429             },
2430             description => 'Retrieve an arbitrary employee\'s locks over the given tsrange',
2431             documentation => <<'EOH',
2432             =pod
2433              
2434             With this resource, administrators can retrieve any employee's locks
2435             over a given tsrange.
2436              
2437             There are no syntactical limitations on the tsrange, but if too many records would
2438             be fetched, the return status will be C<DISPATCH_TOO_MANY_RECORDS_FOUND>.
2439             EOH
2440             },
2441              
2442             # /lock/self/:tsrange
2443             'lock/self/:tsrange' =>
2444             {
2445             parent => 'lock',
2446             handler => {
2447             GET => 'handler_get_lock_self',
2448             },
2449             acl_profile => 'inactive',
2450             cli => 'lock self $TSRANGE',
2451             validations => {
2452             'tsrange' => $tsrange_validation,
2453             },
2454             description => 'Retrieve one\'s own locks over the given tsrange',
2455             documentation => <<'EOH',
2456             =pod
2457              
2458             With this resource, employees can retrieve their own attendance locks
2459             over a given tsrange.
2460              
2461             There are no syntactical limitations on the tsrange, but if too many records would
2462             be fetched, the return status will be C<DISPATCH_TOO_MANY_RECORDS_FOUND>.
2463             EOH
2464             },
2465              
2466             };
2467              
2468              
2469             =head2 Priv (non-history) resources
2470              
2471             =cut
2472              
2473             $defs->{'priv'} = {
2474              
2475             # /priv
2476             'priv' =>
2477             {
2478             parent => '/',
2479             handler => 'handler_noop',
2480             acl_profile => 'passerby',
2481             cli => 'priv',
2482             description => 'Privilege resources',
2483             documentation => <<'EOH',
2484             =pod
2485              
2486             This resource presents a list of subresources, all related to employee privileges.
2487             EOH
2488             },
2489              
2490             # /priv/eid/:eid/?:ts
2491             'priv/eid/:eid/?:ts' =>
2492             {
2493             parent => 'priv',
2494             handler => {
2495             GET => 'handler_priv_get_eid',
2496             },
2497             acl_profile => 'passerby',
2498             cli => 'priv eid $EID [$TIMESTAMP]',
2499             validations => {
2500             'eid' => 'Int',
2501             },
2502             description => 'Get the present privlevel of arbitrary employee, or with optional timestamp, that employee\'s privlevel as of that timestamp',
2503             documentation => <<'EOH',
2504             =pod
2505              
2506             This resource retrieves the privlevel of an arbitrary employee specified by EID.
2507              
2508             If no timestamp is given, the present privlevel is retrieved. If a timestamp
2509             is present, the privlevel as of that timestamp is retrieved.
2510             EOH
2511             },
2512              
2513             # /priv/nick/:nick/?:ts
2514             'priv/nick/:nick/?:ts' =>
2515             {
2516             parent => 'priv',
2517             handler => {
2518             GET => 'handler_priv_get_nick',
2519             },
2520             acl_profile => 'passerby',
2521             cli => 'priv nick $NICK [$TIMESTAMP]',
2522             validations => {
2523             'nick' => $term_validation,
2524             },
2525             description => 'Get the present privlevel of arbitrary employee, or with optional timestamp, that employee\'s privlevel as of that timestamp',
2526             documentation => <<'EOH',
2527             =pod
2528              
2529             This resource retrieves the privlevel of an arbitrary employee specified by nick.
2530              
2531             If no timestamp is given, the present privlevel is retrieved. If a timestamp
2532             is present, the privlevel as of that timestamp is retrieved.
2533             EOH
2534             },
2535              
2536             # /priv/self/?:ts
2537             'priv/self/?:ts' =>
2538             {
2539             parent => 'priv',
2540             handler => {
2541             GET => 'handler_priv_get_self',
2542             },
2543             acl_profile => 'passerby',
2544             cli => 'priv self [$TIMESTAMP]',
2545             description => 'Get the present privlevel of the currently logged-in employee, or with optional timestamp, that employee\'s privlevel as of that timestamp',
2546             documentation => <<'EOH',
2547             =pod
2548              
2549             This resource retrieves the privlevel of the caller (currently logged-in employee).
2550              
2551             If no timestamp is given, the present privlevel is retrieved. If a timestamp
2552             is present, the privlevel as of that timestamp is retrieved.
2553             EOH
2554             },
2555              
2556             };
2557              
2558              
2559             =head2 Schedule (non-history) resources
2560              
2561             =cut
2562              
2563             $defs->{'schedule'} = {
2564              
2565             # /schedule
2566             'schedule' =>
2567             {
2568             parent => '/',
2569             handler => 'handler_noop',
2570             acl_profile => 'passerby',
2571             cli => 'schedule',
2572             description => 'Schedule resources',
2573             documentation => <<'EOH',
2574             =pod
2575              
2576             This resource presents a list of "child" resources (subresources), all of which
2577             are related to schedules.
2578             EOH
2579             },
2580              
2581             # /schedule/all
2582             'schedule/all' =>
2583             {
2584             parent => 'schedule',
2585             handler => {
2586             GET => 'handler_schedule_all',
2587             },
2588             acl_profile => 'inactive',
2589             cli => 'schedule all',
2590             description => 'Retrieves (GET) all non-disabled schedules',
2591             documentation => <<'EOH',
2592             =pod
2593              
2594             This resource returns a list (array) of all schedules for which the 'disabled' field has
2595             either not been set or has been set to 'false'.
2596             EOH
2597             },
2598              
2599             # /schedule/all/disabled
2600             'schedule/all/disabled' =>
2601             {
2602             parent => 'schedule/all',
2603             handler => {
2604             GET => 'handler_schedule_all',
2605             },
2606             acl_profile => 'admin',
2607             cli => 'schedule all disabled',
2608             description => 'Retrieves (GET) all schedules (disabled and non-disabled)',
2609             documentation => <<'EOH',
2610             =pod
2611              
2612             This resource returns a list (array) of all schedules, regardless of the contents
2613             of the 'disabled' field.
2614             EOH
2615             },
2616              
2617             # /schedule/eid/:eid/?:ts
2618             'schedule/eid/:eid/?:ts' =>
2619             {
2620             parent => 'schedule',
2621             handler => {
2622             GET => 'handler_get_schedule_eid',
2623             },
2624             acl_profile => 'passerby',
2625             cli => 'schedule eid $EID [$TIMESTAMP]',
2626             validations => {
2627             'eid' => 'Int',
2628             },
2629             description => 'Get the current schedule of arbitrary employee, or with optional timestamp, that employee\'s schedule as of that timestamp',
2630             documentation => <<'EOH',
2631             =pod
2632              
2633             This resource retrieves the schedule of an arbitrary employee specified by EID.
2634              
2635             If no timestamp is given, the current schedule is retrieved. If a timestamp
2636             is present, the schedule as of that timestamp is retrieved.
2637             EOH
2638             },
2639              
2640             # /schedule/new
2641             'schedule/new' =>
2642             {
2643             parent => 'schedule',
2644             handler => {
2645             POST => 'handler_schedule_new',
2646             },
2647             acl_profile => 'admin',
2648             cli => 'schedule new $JSON',
2649             description => 'Insert schedules',
2650             documentation => <<'EOH',
2651             =pod
2652              
2653             Given a set of intervals, all of which must fall within a single contiguous
2654             168-hour (7-day) period, this resource performs all actions necessary to either
2655             create a new schedule from those intervals or verify that an equivalent
2656             schedule already exists.
2657              
2658             Sample JSON:
2659              
2660             { "schedule" : [
2661             "[2014-09-22 08:00, 2014-09-22 12:00)",
2662             "[2014-09-22 12:30, 2014-09-22 16:30)",
2663             "[2014-09-23 08:00, 2014-09-23 12:00)",
2664             "[2014-09-23 12:30, 2014-09-23 16:30)",
2665             "[2014-09-24 08:00, 2014-09-24 12:00)",
2666             "[2014-09-24 12:30, 2014-09-24 16:30)",
2667             "[2014-09-25 08:00, 2014-09-25 12:00)",
2668             "[2014-09-25 12:30, 2014-09-25 16:30)"
2669             ] }
2670              
2671             (Optionally, an scode can be assigned by including an "scode" property.)
2672              
2673             Read on for details:
2674              
2675             First, a set of scratch intervals is created in the 'schedintvls' table.
2676             If this succeeds, an INSERT operation is used to create a new record in the
2677             'schedule' table. This operation has two possible successful outcomes
2678             depending on whether such a schedule already existed in the database, or not.
2679             The status codes for these outcomes are DISPATCH_SCHEDULE_OK and
2680             DISPATCH_SCHEDULE_INSERT_OK, respectively.
2681              
2682             In both cases, the underlying scratch intervals are deleted automatically.
2683             (All operations on the 'schedintlvs' table are supposed to be hidden from
2684             Dochazka clients.)
2685              
2686             Note that many sets of intervals can map to a single schedule (the conversion
2687             process is only interested in the day of the week), so this resource may return
2688             DISPATCH_SCHEDULE_OK more often than you think.
2689              
2690             Whether or not the exact schedule existed already, if the underlying database
2691             operation is successful the payload will contain three properties: 'sid' (the
2692             SID assigned to the schedule containing the intervals), 'intervals' (the
2693             intervals themselves), and 'schedule' (the intervals as they appear after being
2694             converted into the format suitable for insertion into the 'schedule' table).
2695              
2696             N.B. At present there is no way to just check for the existence of a schedule
2697             corresponding to a given set of intervals.
2698             EOH
2699             },
2700              
2701             # /schedule/nick/:nick/?:ts
2702             'schedule/nick/:nick/?:ts' =>
2703             {
2704             parent => 'schedule',
2705             handler => {
2706             GET => 'handler_get_schedule_nick',
2707             },
2708             acl_profile => 'admin',
2709             cli => 'schedule nick $NICK [$TIMESTAMP]',
2710             validations => {
2711             'nick' => $term_validation,
2712             },
2713             description => 'Get the current schedule of arbitrary employee, or with optional timestamp, that employee\'s schedule as of that timestamp',
2714             documentation => <<'EOH',
2715             =pod
2716              
2717             This resource retrieves the schedule of an arbitrary employee specified by nick.
2718              
2719             If no timestamp is given, the current schedule is retrieved. If a timestamp
2720             is present, the schedule as of that timestamp is retrieved.
2721             EOH
2722             },
2723              
2724             # /schedule/scode/:scode
2725             'schedule/scode/:scode' =>
2726             {
2727             parent => 'schedule',
2728             handler => {
2729             GET => 'handler_get_schedule_scode',
2730             PUT => 'handler_put_schedule_scode',
2731             DELETE => 'handler_delete_schedule_scode',
2732             },
2733             acl_profile => {
2734             GET => 'inactive',
2735             PUT => 'admin',
2736             DELETE => 'admin',
2737             },
2738             cli => 'schedule scode $scode',
2739             validations => {
2740             'scode' => qr/^[[:alnum:]_][[:alnum:]_-]*$/,
2741             },
2742             description => 'Retrieves, updates, or deletes a schedule by its scode',
2743             documentation => <<'EOH',
2744             =pod
2745              
2746             This resource makes it possible to GET, PUT, or DELETE a schedule by its scode.
2747              
2748             =over
2749              
2750             =item * GET
2751              
2752             An scode (string) must be given as a URI parameter. If a schedule with this
2753             scode is found (exact, case-sensitive match), it is returned in the payload.
2754              
2755             =item * PUT
2756              
2757             This resource/method provides a way to set (modify) the 'scode', 'remark'
2758             and/or 'disabled' fields of a schedule record. Simply provide the property (or
2759             properties) and the new value(s) in the request body, e.g.:
2760              
2761             { "scode" : "WIGWAM" }
2762              
2763             or
2764              
2765             { "remark" : "foobar", "disabled" : "t" }
2766              
2767             Properties other than these three cannot be modified using this resource.
2768              
2769             =item * DELETE
2770              
2771             The scode must be given as an URI parameter. If found, the schedule with that
2772             scode will be deleted in an atomic operation. If the operation is successful the
2773             return status will be "OK".
2774              
2775             =back
2776             EOH
2777             },
2778              
2779             # /schedule/self/?:ts
2780             'schedule/self/?:ts' =>
2781             {
2782             parent => 'schedule',
2783             handler => {
2784             GET => 'handler_get_schedule_self',
2785             },
2786             acl_profile => 'passerby',
2787             cli => 'schedule current [$TIMESTAMP]',
2788             description => 'Get the current schedule of the currently logged-in employee, or with optional timestamp, that employee\'s schedule as of that timestamp',
2789             documentation => <<'EOH',
2790             =pod
2791              
2792             This resource retrieves the schedule of the caller (currently logged-in employee).
2793              
2794             If no timestamp is given, the current schedule is retrieved. If a timestamp
2795             is present, the schedule as of that timestamp is retrieved.
2796             EOH
2797             },
2798              
2799             # /schedule/sid/:sid
2800             'schedule/sid/:sid' =>
2801             {
2802             parent => 'schedule',
2803             handler => {
2804             GET => 'handler_get_schedule_sid',
2805             PUT => 'handler_put_schedule_sid',
2806             DELETE => 'handler_delete_schedule_sid',
2807             },
2808             acl_profile => {
2809             GET => 'passerby',
2810             PUT => 'admin',
2811             DELETE => 'admin',
2812             },
2813             cli => 'schedule sid $SID',
2814             validations => {
2815             'sid' => 'Int',
2816             },
2817             description => 'Retrieves, updates, or deletes a schedule by its SID',
2818             documentation => <<'EOH',
2819             =pod
2820              
2821             This resource makes it possible to GET, PUT, or DELETE a schedule by its SID.
2822              
2823             =over
2824              
2825             =item * GET
2826              
2827             An integer SID must be given as an URI parameter. If a schedule
2828             with this SID is found, it is returned in the payload.
2829              
2830             =item * PUT
2831              
2832             This resource/method provides a way to set (modify) the 'scode', 'remark'
2833             and/or 'disabled' fields of a schedule record. Simply provide the property (or
2834             properties) and the new value(s) in the request body, e.g.:
2835              
2836             { "scode" : "WIGWAM" }
2837              
2838             or
2839              
2840             { "remark" : "foobar", "disabled" : "t" }
2841              
2842             Properties other than these three cannot be modified using this resource.
2843              
2844             =item * DELETE
2845              
2846             An integer SID must be given as an URI parameter. If found, the schedule with
2847             that SID will be deleted in an atomic operation. If the operation is successful
2848             the return status will be "OK".
2849              
2850             =back
2851             EOH
2852             },
2853              
2854             };
2855              
2856              
2857              
2858             =head1 FUNCTIONS
2859              
2860             =head2 load
2861              
2862             Load all the resource definitions into the L<Path::Router> instance.
2863              
2864             =cut
2865              
2866             sub load {
2867 0     0 1   foreach my $prop ( qw( top activity component employee genreport
2868             history interval lock priv schedule ) ) {
2869 0 0         Web::MREST::InitRouter::load_resource_defs( $defs->{$prop} ) if $defs->{$prop};
2870             }
2871             }
2872              
2873              
2874             1;