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