App-Dochazka-CLI

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

- CLI.pm: document commands and their syntax
- Parser.pm: work on top-level GET commands

0.014  2014-10-19 08:44 CEST
- move command POD to Parser.pm where it belongs
- Parser.pm: add a couple more top-level GET commands

0.015  2014-10-19 13:35 CEST
- HTTP.pm: fix send_req so it is capable of sending requests with methods other
  than GET
- Parser.pm: add PUT and PUT HELP commands

0.016  2014-10-19 13:53 CEST
- HTTP.pm, Parser.pm: cleanup

0.017  2014-10-19 22:33 CEST
- implement more resources

0.018  2014-10-20 08:32 CEST
- Parser.pm: fix brokenness in 'GET WHOAMI' and 'PUT EMPLOYEE'

0.019  2014-10-20 17:23 CEST
- Parser.pm: fix a silly bug

0.020  2014-10-20 22:09 CEST
- Parser.pm: add 'GET CURRENT PRIV' command
- bin/dochazka-cli: fix privilege brokenness; add status text to command output

0.021  2014-10-21 10:44 CEST
- Parser.pm: add 'GET EMPLOYEE COUNT' and get rid of conflicting 'GET
  EMPLOYEE [STRING]'

0.022  2014-10-21 16:26 CEST
- bin/dochazka-cli: show response body on NOTICE status as well as OK
- HTTP.pm: explicitly import GET PUT POST DELETE from HTTP::Request::Common
- Parser.pm: properly implement 'metaparam/:param' and 'not_implemented'
  resources

0.023  2014-10-21 22:24 CEST
- Parser.pm: fix $anything regex variable; support 'forbidden' resource; add
  other missing top-level resources so now all are supported

0.024  2014-10-22 16:42 CEST
- Parser.pm: add POST EMPLOYEE EID command

Changes  view on Meta::CPAN

- complete development workflow for employee resources
- Parser.pm: add missing documentation and commands

0.028  2014-10-24 15:27 CEST
- Parser.pm: add privhistory commands

0.029  2014-10-24 22:34 CEST
- bin/dochazka-cli: fix bug "hitting ENTER at CLI prompt causes over a
  screenful of error messages to be displayed"
- Parser.pm: document and implement commands: 
  - PUT PRIVHISTORY EID 
  - PUT PRIVHISTORY NICK
  - DELETE PRIVHISTORY EID 
  - DELETE PRIVHISTORY NICK

0.030  2014-10-25 12:05 CEST
- bin/dochazka-cli: write a proper SYNOPSIS; add an optional 'sitedir'
  command-line option; fix bug "dochazka-cli refuses to start unless
  /etc/dochazka-cli directory exists and contains an empty file named
  CLI_SiteConfig.pm"

0.031  2014-10-25 23:20 CEST

Changes  view on Meta::CPAN

0.038  2014-10-28 09:29 CET
- Parser.pm: handle activity resources; add '$method activity all' commands

0.039  2014-10-29 09:31 CET
- Parser.pm: support 'activity/all/disabled' resource

0.040  2014-10-29 10:31 CET
- Parser.pm: support 'activity/aid/:aid'

0.041  2014-10-29 13:50 CET
- Parser.pm: support PUT and DELETE requests for 'activity/aid/:aid'

0.042  2014-10-29 16:40 CET
- Parser.pm: support "/activity/code/:code"

0.043  2014-10-29 22:53 CET
- Parser.pm: support POST on 'activity/aid/:aid' and 'activity/code/:code',
  even if just to verify 405 result

0.044  2014-10-30 18:20 CET
- Parser.pm: support 'activity/aid' and 'activity/code' resources

config/CLI_Config.pm  view on Meta::CPAN

# -----------------------------------

# DOCHAZKA_REST_LOGIN_NICK
#     nick to use when we authenticate ourselves to the App::Dochazka::REST server
#     when this is set to '' or undef, App::Dochazka::CLI will prompt for it
set( 'DOCHAZKA_REST_LOGIN_NICK', undef );

# DOCHAZKA_REST_LOGIN_NICK
#     password to use when we authenticate ourselves to the App::Dochazka::REST server
#     when this is set to '' or undef, App::Dochazka::CLI will prompt for a password
#     WARNING: PUTTING YOUR PASSWORD HERE MAY BE CONVENIENT, BUT IS PROBABLY UNSAFE
set( 'DOCHAZKA_REST_LOGIN_PASSWORD', undef );

# MREST_CLI_COOKIE_JAR
#     default location of the cookie jar
set( 'MREST_CLI_COOKIE_JAR', "$ENV{HOME}/.cookies.txt" );

# DOCHAZKA_CLI_LOG_FILE
#     default location of the log file
set( 'DOCHAZKA_CLI_LOG_FILE', "$ENV{HOME}/.dochazka-cli.log" );

config/CLI_Message_en.conf  view on Meta::CPAN

Privilege history record (PHID %s) added

# DOCHAZKA_CLI_SCHEDULE_HISTORY_ADD
DOCHAZKA_CLI_SCHEDULE_HISTORY_ADD
Schedule history record (SHID %s) added

# DOCHAZKA_CLI_NO_MATCH
DOCHAZKA_CLI_NO_MATCH
Does not match

# TSRANGE_DOES_NOT_COMPUTE
TSRANGE_DOES_NOT_COMPUTE
One or both of the timestamps does not compute

# DOCHAZKA_CLI_INVALID_DATE_OR_TIME
DOCHAZKA_CLI_INVALID_DATE_OR_TIME
Encountered invalid date or time ->%s<-

# DOCHAZKA_CLI_PROMPT_DATE_CHANGED
DOCHAZKA_CLI_PROMPT_DATE_CHANGED
Prompt date changed to %s

ext/CLI_SiteConfig.pm.example  view on Meta::CPAN

#

# DOCHAZKA_REST_LOGIN_NICK
#     nick to use when we authenticate ourselves to the App::Dochazka::REST server
#     when this is set to '' or undef, App::Dochazka::CLI will prompt for it
#set( 'DOCHAZKA_REST_LOGIN_NICK', undef );

# DOCHAZKA_REST_LOGIN_NICK
#     password to use when we authenticate ourselves to the App::Dochazka::REST server
#     when this is set to '' or undef, App::Dochazka::CLI will prompt for a password
#     WARNING: PUTTING YOUR PASSWORD HERE MAY BE CONVENIENT, BUT IS PROBABLY UNSAFE
#set( 'DOCHAZKA_REST_LOGIN_PASSWORD', undef );

# MREST_CLI_COOKIE_JAR
#     default location of the cookie jar
#set( 'MREST_CLI_COOKIE_JAR', "$ENV{HOME}/.cookies.txt" );

# DOCHAZKA_CLI_LOG_FILE
#     default location of the log file
#set( 'DOCHAZKA_CLI_LOG_FILE', "$ENV{HOME}/.dochazka-cli.log" );

lib/App/Dochazka/CLI/CommandMap.pm  view on Meta::CPAN

require App::Dochazka::CLI::Commands::RestTest::Interval;
require App::Dochazka::CLI::Commands::RestTest::Lock;
require App::Dochazka::CLI::Commands::RestTest::Priv;
require App::Dochazka::CLI::Commands::RestTest::Schedule;
require App::Dochazka::CLI::Commands::RestTest::Top;

our $dispatch_map = { 

    # Top-level commands
    "GET" => \&_method,
    "PUT" => \&_method,
    "POST" => \&_method,
    "DELETE" => \&_method,
    "GET BUGREPORT" => \&_method_bugreport,
    "PUT BUGREPORT" => \&_method_bugreport,
    "POST BUGREPORT" => \&_method_bugreport,
    "DELETE BUGREPORT" => \&_method_bugreport,
    "GET CONFIGINFO" => \&_method_configinfo,
    "PUT CONFIGINFO" => \&_method_configinfo,
    "POST CONFIGINFO" => \&_method_configinfo,
    "DELETE CONFIGINFO" => \&_method_configinfo,
    "GET COOKIEJAR" => \&_method_cookiejar,
    "PUT COOKIEJAR" => \&_method_cookiejar,
    "POST COOKIEJAR" => \&_method_cookiejar,
    "DELETE COOKIEJAR" => \&_method_cookiejar,
    "GET DBSTATUS" => \&_method_dbstatus,
    "PUT DBSTATUS" => \&_method_dbstatus,
    "POST DBSTATUS" => \&_method_dbstatus,
    "DELETE DBSTATUS" => \&_method_dbstatus,
    "GET DOCU" => \&_method_docu,
    "PUT DOCU" => \&_method_docu,
    "POST DOCU" => \&_method_docu,
    "DELETE DOCU" => \&_method_docu,
    "GET DOCU POD" => \&_method_docu_pod,
    "PUT DOCU POD" => \&_method_docu_pod,
    "POST DOCU POD" => \&_method_docu_pod,
    "DELETE DOCU POD" => \&_method_docu_pod,
    "GET DOCU POD _DOCU" => \&_method_docu_pod_docu,
    "PUT DOCU POD _DOCU" => \&_method_docu_pod_docu,
    "POST DOCU POD _DOCU" => \&_method_docu_pod_docu,
    "DELETE DOCU POD _DOCU" => \&_method_docu_pod_docu,
    "GET HOLIDAY _TSRANGE" => \&_method_holiday_tsrange,
    "PUT HOLIDAY _TSRANGE" => \&_method_holiday_tsrange,
    "POST HOLIDAY _TSRANGE" => \&_method_holiday_tsrange,
    "DELETE HOLIDAY _TSRANGE" => \&_method_holiday_tsrange,
    "GET DOCU HTML" => \&_method_docu_html,
    "PUT DOCU HTML" => \&_method_docu_html,
    "POST DOCU HTML" => \&_method_docu_html,
    "DELETE DOCU HTML" => \&_method_docu_html,
    "GET DOCU HTML _DOCU" => \&_method_docu_html_docu,
    "PUT DOCU HTML _DOCU" => \&_method_docu_html_docu,
    "POST DOCU HTML _DOCU" => \&_method_docu_html_docu,
    "DELETE DOCU HTML _DOCU" => \&_method_docu_html_docu,
    "GET DOCU TEXT" => \&_method_docu_text,
    "PUT DOCU TEXT" => \&_method_docu_text,
    "POST DOCU TEXT" => \&_method_docu_text,
    "DELETE DOCU TEXT" => \&_method_docu_text,
    "GET DOCU TEXT _DOCU" => \&_method_docu_text_docu,
    "PUT DOCU TEXT _DOCU" => \&_method_docu_text_docu,
    "POST DOCU TEXT _DOCU" => \&_method_docu_text_docu,
    "DELETE DOCU TEXT _DOCU" => \&_method_docu_text_docu,
    "GET ECHO" => \&_method_echo,
    "PUT ECHO" => \&_method_echo,
    "POST ECHO" => \&_method_echo,
    "DELETE ECHO" => \&_method_echo,
    "GET FORBIDDEN" => \&_method_forbidden,
    "PUT FORBIDDEN" => \&_method_forbidden,
    "POST FORBIDDEN" => \&_method_forbidden,
    "DELETE FORBIDDEN" => \&_method_forbidden,
    "GET NOOP" => \&_method_noop,
    "PUT NOOP" => \&_method_noop,
    "POST NOOP" => \&_method_noop,
    "DELETE NOOP" => \&_method_noop,
    "GET PARAM" => \&_method_param,
    "PUT PARAM" => \&_method_param,
    "POST PARAM" => \&_method_param,
    "DELETE PARAM" => \&_method_param,
    "GET PARAM CORE" => \&_method_param_core,
    "PUT PARAM CORE" => \&_method_param_core,
    "POST PARAM CORE" => \&_method_param_core,
    "DELETE PARAM CORE" => \&_method_param_core,
    "GET PARAM CORE _TERM" => \&_method_param_core_term,
    "PUT PARAM CORE _TERM" => \&_method_param_core_term,
    "POST PARAM CORE _TERM" => \&_method_param_core_term,
    "DELETE PARAM CORE _TERM" => \&_method_param_core_term,
    "GET PARAM META" => \&_method_param_meta,
    "PUT PARAM META" => \&_method_param_meta,
    "POST PARAM META" => \&_method_param_meta,
    "DELETE PARAM META" => \&_method_param_meta,
    "GET PARAM META _TERM" => \&_method_param_meta_term,
    "PUT PARAM META _TERM" => \&_method_param_meta_term,
    "POST PARAM META _TERM" => \&_method_param_meta_term,
    "DELETE PARAM META _TERM" => \&_method_param_meta_term,
    "GET PARAM SITE" => \&_method_param_site,
    "PUT PARAM SITE" => \&_method_param_site,
    "POST PARAM SITE" => \&_method_param_site,
    "DELETE PARAM SITE" => \&_method_param_site,
    "GET PARAM SITE _TERM" => \&_method_param_site_term,
    "PUT PARAM SITE _TERM" => \&_method_param_site_term,
    "POST PARAM SITE _TERM" => \&_method_param_site_term,
    "DELETE PARAM SITE _TERM" => \&_method_param_site_term,
    "GET SESSION" => \&_method_session,
    "PUT SESSION" => \&_method_session,
    "POST SESSION" => \&_method_session,
    "DELETE SESSION" => \&_method_session,
    "GET VERSION" => \&_method_version,
    "PUT VERSION" => \&_method_version,
    "POST VERSION" => \&_method_version,
    "DELETE VERSION" => \&_method_version,
    "GET WHOAMI" => \&_method_whoami,
    "PUT WHOAMI" => \&_method_whoami,
    "POST WHOAMI" => \&_method_whoami,
    "DELETE WHOAMI" => \&_method_whoami,
    "EXIT" => \&go_exit,

    # Activity commands
    "GET ACTIVITY" => \&_method_activity,
    "PUT ACTIVITY" => \&_method_activity,
    "POST ACTIVITY" => \&_method_activity,
    "DELETE ACTIVITY" => \&_method_activity,
    "GET ACTIVITY AID" => \&_method_activity_aid,
    "PUT ACTIVITY AID" => \&_method_activity_aid,
    "POST ACTIVITY AID" => \&_method_activity_aid,
    "DELETE ACTIVITY AID" => \&_method_activity_aid,
    "GET ACTIVITY AID _JSON" => \&_method_activity_aid,
    "PUT ACTIVITY AID _JSON" => \&_method_activity_aid,
    "POST ACTIVITY AID _JSON" => \&_method_activity_aid,
    "DELETE ACTIVITY AID _JSON" => \&_method_activity_aid,
    "GET ACTIVITY AID _NUM" => \&_method_activity_aid_num,
    "PUT ACTIVITY AID _NUM" => \&_method_activity_aid_num,
    "POST ACTIVITY AID _NUM" => \&_method_activity_aid_num,
    "DELETE ACTIVITY AID _NUM" => \&_method_activity_aid_num,
    "GET ACTIVITY ALL" => \&_method_activity_all,
    "PUT ACTIVITY ALL" => \&_method_activity_all,
    "POST ACTIVITY ALL" => \&_method_activity_all,
    "DELETE ACTIVITY ALL" => \&_method_activity_all,
    "GET ACTIVITY ALL DISABLED" => \&_method_activity_all_disabled,
    "PUT ACTIVITY ALL DISABLED" => \&_method_activity_all_disabled,
    "POST ACTIVITY ALL DISABLED" => \&_method_activity_all_disabled,
    "DELETE ACTIVITY ALL DISABLED" => \&_method_activity_all_disabled,
    "GET ACTIVITY CODE" => \&_method_activity_code,
    "PUT ACTIVITY CODE" => \&_method_activity_code,
    "POST ACTIVITY CODE" => \&_method_activity_code,
    "DELETE ACTIVITY CODE" => \&_method_activity_code,
    "GET ACTIVITY CODE _JSON" => \&_method_activity_code,
    "PUT ACTIVITY CODE _JSON" => \&_method_activity_code,
    "POST ACTIVITY CODE _JSON" => \&_method_activity_code,
    "DELETE ACTIVITY CODE _JSON" => \&_method_activity_code,
    "GET ACTIVITY CODE _TERM" => \&_method_activity_code_term,
    "PUT ACTIVITY CODE _TERM" => \&_method_activity_code_term,
    "POST ACTIVITY CODE _TERM" => \&_method_activity_code_term,
    "DELETE ACTIVITY CODE _TERM" => \&_method_activity_code_term,

    # Employee commands
    "GET EMPLOYEE" => \&_method_employee,
    "PUT EMPLOYEE" => \&_method_employee,
    "POST EMPLOYEE" => \&_method_employee,
    "DELETE EMPLOYEE" => \&_method_employee,
    "GET EMPLOYEE COUNT" => \&_method_employee_count,
    "PUT EMPLOYEE COUNT" => \&_method_employee_count,
    "POST EMPLOYEE COUNT" => \&_method_employee_count,
    "DELETE EMPLOYEE COUNT" => \&_method_employee_count,
    "GET EMPLOYEE COUNT PRIV" => \&_method_employee_count_priv,
    "PUT EMPLOYEE COUNT PRIV" => \&_method_employee_count_priv,
    "POST EMPLOYEE COUNT PRIV" => \&_method_employee_count_priv,
    "DELETE EMPLOYEE COUNT PRIV" => \&_method_employee_count_priv,
    "GET EMPLOYEE EID" => \&_method_employee_eid,
    "PUT EMPLOYEE EID" => \&_method_employee_eid,
    "POST EMPLOYEE EID" => \&_method_employee_eid,
    "DELETE EMPLOYEE EID" => \&_method_employee_eid,
    "GET EMPLOYEE EID _JSON" => \&_method_employee_eid_json,
    "PUT EMPLOYEE EID _JSON" => \&_method_employee_eid_json,
    "POST EMPLOYEE EID _JSON" => \&_method_employee_eid_json,
    "DELETE EMPLOYEE EID _JSON" => \&_method_employee_eid_json,
    "GET EMPLOYEE EID _NUM" => \&_method_employee_eid_num,
    "PUT EMPLOYEE EID _NUM" => \&_method_employee_eid_num,
    "POST EMPLOYEE EID _NUM" => \&_method_employee_eid_num,
    "DELETE EMPLOYEE EID _NUM" => \&_method_employee_eid_num,
    "GET EMPLOYEE EID _NUM _JSON" => \&_method_employee_eid_num_json,
    "PUT EMPLOYEE EID _NUM _JSON" => \&_method_employee_eid_num_json,
    "POST EMPLOYEE EID _NUM _JSON" => \&_method_employee_eid_num_json,
    "DELETE EMPLOYEE EID _NUM _JSON" => \&_method_employee_eid_num_json,
    "GET EMPLOYEE EID _NUM TEAM" => \&_method_employee_eid_num_team,
    "PUT EMPLOYEE EID _NUM TEAM" => \&_method_employee_eid_num_team,
    "POST EMPLOYEE EID _NUM TEAM" => \&_method_employee_eid_num_team,
    "DELETE EMPLOYEE EID _NUM TEAM" => \&_method_employee_eid_num_team,
    "GET EMPLOYEE LIST" => \&_method_employee_list,
    "PUT EMPLOYEE LIST" => \&_method_employee_list,
    "POST EMPLOYEE LIST" => \&_method_employee_list,
    "DELETE EMPLOYEE LIST" => \&_method_employee_list,
    "GET EMPLOYEE LIST _TERM" => \&_method_employee_list_priv,
    "PUT EMPLOYEE LIST _TERM" => \&_method_employee_list_priv,
    "POST EMPLOYEE LIST _TERM" => \&_method_employee_list_priv,
    "DELETE EMPLOYEE LIST _TERM" => \&_method_employee_list_priv,
    "GET EMPLOYEE NICK" => \&_method_employee_nick,
    "PUT EMPLOYEE NICK" => \&_method_employee_nick,
    "POST EMPLOYEE NICK" => \&_method_employee_nick,
    "DELETE EMPLOYEE NICK" => \&_method_employee_nick,
    "GET EMPLOYEE NICK _JSON" => \&_method_employee_nick_json,
    "PUT EMPLOYEE NICK _JSON" => \&_method_employee_nick_json,
    "POST EMPLOYEE NICK _JSON" => \&_method_employee_nick_json,
    "DELETE EMPLOYEE NICK _JSON" => \&_method_employee_nick_json,
    "GET EMPLOYEE NICK _TERM" => \&_method_employee_nick_term,
    "PUT EMPLOYEE NICK _TERM" => \&_method_employee_nick_term,
    "POST EMPLOYEE NICK _TERM" => \&_method_employee_nick_term,
    "DELETE EMPLOYEE NICK _TERM" => \&_method_employee_nick_term,
    "GET EMPLOYEE NICK _TERM LDAP" => \&_method_employee_nick_term_ldap,
    "PUT EMPLOYEE NICK _TERM LDAP" => \&_method_employee_nick_term_ldap,
    "POST EMPLOYEE NICK _TERM LDAP" => \&_method_employee_nick_term_ldap,
    "DELETE EMPLOYEE NICK _TERM LDAP" => \&_method_employee_nick_term_ldap,
    "GET EMPLOYEE NICK _TERM _JSON" => \&_method_employee_nick_term_json,
    "PUT EMPLOYEE NICK _TERM _JSON" => \&_method_employee_nick_term_json,
    "POST EMPLOYEE NICK _TERM _JSON" => \&_method_employee_nick_term_json,
    "DELETE EMPLOYEE NICK _TERM _JSON" => \&_method_employee_nick_term_json,
    "GET EMPLOYEE NICK _TERM TEAM" => \&_method_employee_nick_term_team,
    "PUT EMPLOYEE NICK _TERM TEAM" => \&_method_employee_nick_term_team,
    "POST EMPLOYEE NICK _TERM TEAM" => \&_method_employee_nick_term_team,
    "DELETE EMPLOYEE NICK _TERM TEAM" => \&_method_employee_nick_term_team,
    "GET EMPLOYEE SEARCH" => \&_method_employee_search,
    "PUT EMPLOYEE SEARCH" => \&_method_employee_search,
    "POST EMPLOYEE SEARCH" => \&_method_employee_search,
    "DELETE EMPLOYEE SEARCH" => \&_method_employee_search,
    "GET EMPLOYEE SEARCH NICK _TERM" => \&_method_employee_search_nick,
    "PUT EMPLOYEE SEARCH NICK _TERM" => \&_method_employee_search_nick,
    "POST EMPLOYEE SEARCH NICK _TERM" => \&_method_employee_search_nick,
    "DELETE EMPLOYEE SEARCH NICK _TERM" => \&_method_employee_search_nick,
    "GET EMPLOYEE SELF" => \&_method_employee_self,
    "PUT EMPLOYEE SELF" => \&_method_employee_self,
    "POST EMPLOYEE SELF" => \&_method_employee_self,
    "DELETE EMPLOYEE SELF" => \&_method_employee_self,
    "GET EMPLOYEE SELF FULL" => \&_method_employee_self_full,
    "PUT EMPLOYEE SELF FULL" => \&_method_employee_self_full,
    "POST EMPLOYEE SELF FULL" => \&_method_employee_self_full,
    "DELETE EMPLOYEE SELF FULL" => \&_method_employee_self_full,
    "GET EMPLOYEE TEAM" => \&_method_employee_team,
    "PUT EMPLOYEE TEAM" => \&_method_employee_team,
    "POST EMPLOYEE TEAM" => \&_method_employee_team,
    "DELETE EMPLOYEE TEAM" => \&_method_employee_team,

    # Interval commands
    "GET INTERVAL" => \&_method_interval,
    "PUT INTERVAL" => \&_method_interval,
    "POST INTERVAL" => \&_method_interval,
    "DELETE INTERVAL" => \&_method_interval,
    "GET INTERVAL EID _NUM" => \&_method_interval_eid,
    "PUT INTERVAL EID _NUM" => \&_method_interval_eid,
    "POST INTERVAL EID _NUM" => \&_method_interval_eid,
    "DELETE INTERVAL EID _NUM" => \&_method_interval_eid,
    "GET INTERVAL EID _NUM _TSRANGE" => \&_method_interval_eid_tsrange,
    "PUT INTERVAL EID _NUM _TSRANGE" => \&_method_interval_eid_tsrange,
    "POST INTERVAL EID _NUM _TSRANGE" => \&_method_interval_eid_tsrange,
    "DELETE INTERVAL EID _NUM _TSRANGE" => \&_method_interval_eid_tsrange,
    "GET INTERVAL FILLUP" => \&_method_interval_fillup,
    "PUT INTERVAL FILLUP" => \&_method_interval_fillup,
    "POST INTERVAL FILLUP" => \&_method_interval_fillup,
    "DELETE INTERVAL FILLUP" => \&_method_interval_fillup,
    "GET INTERVAL IID _NUM" => \&_method_interval_iid,
    "PUT INTERVAL IID _NUM" => \&_method_interval_iid,
    "POST INTERVAL IID _NUM" => \&_method_interval_iid,
    "DELETE INTERVAL IID _NUM" => \&_method_interval_iid,
    "GET INTERVAL NEW" => \&_method_interval_new,
    "PUT INTERVAL NEW" => \&_method_interval_new,
    "POST INTERVAL NEW" => \&_method_interval_new,
    "DELETE INTERVAL NEW" => \&_method_interval_new,
    "GET INTERVAL NICK _TERM" => \&_method_interval_nick,
    "PUT INTERVAL NICK _TERM" => \&_method_interval_nick,
    "POST INTERVAL NICK _TERM" => \&_method_interval_nick,
    "DELETE INTERVAL NICK _TERM" => \&_method_interval_nick,
    "GET INTERVAL NICK _TERM _TSRANGE" => \&_method_interval_nick_tsrange,
    "PUT INTERVAL NICK _TERM _TSRANGE" => \&_method_interval_nick_tsrange,
    "POST INTERVAL NICK _TERM _TSRANGE" => \&_method_interval_nick_tsrange,
    "DELETE INTERVAL NICK _TERM _TSRANGE" => \&_method_interval_nick_tsrange,
    "GET INTERVAL SELF" => \&_method_interval_self,
    "PUT INTERVAL SELF" => \&_method_interval_self,
    "POST INTERVAL SELF" => \&_method_interval_self,
    "DELETE INTERVAL SELF" => \&_method_interval_self,
    "GET INTERVAL SELF _TSRANGE" => \&_method_interval_self_tsrange,
    "PUT INTERVAL SELF _TSRANGE" => \&_method_interval_self_tsrange,
    "POST INTERVAL SELF _TSRANGE" => \&_method_interval_self_tsrange,
    "DELETE INTERVAL SELF _TSRANGE" => \&_method_interval_self_tsrange,

    # Lock commands
    "GET LOCK" => \&_method_lock,
    "PUT LOCK" => \&_method_lock,
    "POST LOCK" => \&_method_lock,
    "DELETE LOCK" => \&_method_lock,
    "GET LOCK EID _NUM" => \&_method_lock_eid,
    "PUT LOCK EID _NUM" => \&_method_lock_eid,
    "POST LOCK EID _NUM" => \&_method_lock_eid,
    "DELETE LOCK EID _NUM" => \&_method_lock_eid,
    "GET LOCK EID _NUM _TSRANGE" => \&_method_lock_eid_tsrange,
    "PUT LOCK EID _NUM _TSRANGE" => \&_method_lock_eid_tsrange,
    "POST LOCK EID _NUM _TSRANGE" => \&_method_lock_eid_tsrange,
    "DELETE LOCK EID _NUM _TSRANGE" => \&_method_lock_eid_tsrange,
    "GET LOCK LID _NUM" => \&_method_lock_lid,
    "PUT LOCK LID _NUM" => \&_method_lock_lid,
    "POST LOCK LID _NUM" => \&_method_lock_lid,
    "DELETE LOCK LID _NUM" => \&_method_lock_lid,
    "GET LOCK NEW" => \&_method_lock_new,
    "PUT LOCK NEW" => \&_method_lock_new,
    "POST LOCK NEW" => \&_method_lock_new,
    "DELETE LOCK NEW" => \&_method_lock_new,
    "GET LOCK NICK _TERM" => \&_method_lock_nick,
    "PUT LOCK NICK _TERM" => \&_method_lock_nick,
    "POST LOCK NICK _TERM" => \&_method_lock_nick,
    "DELETE LOCK NICK _TERM" => \&_method_lock_nick,
    "GET LOCK NICK _TERM _TSRANGE" => \&_method_lock_nick_tsrange,
    "PUT LOCK NICK _TERM _TSRANGE" => \&_method_lock_nick_tsrange,
    "POST LOCK NICK _TERM _TSRANGE" => \&_method_lock_nick_tsrange,
    "DELETE LOCK NICK _TERM _TSRANGE" => \&_method_lock_nick_tsrange,
    "GET LOCK SELF" => \&_method_lock_self,
    "PUT LOCK SELF" => \&_method_lock_self,
    "POST LOCK SELF" => \&_method_lock_self,
    "DELETE LOCK SELF" => \&_method_lock_self,
    "GET LOCK SELF _TSRANGE" => \&_method_lock_self_tsrange,
    "PUT LOCK SELF _TSRANGE" => \&_method_lock_self_tsrange,
    "POST LOCK SELF _TSRANGE" => \&_method_lock_self_tsrange,
    "DELETE LOCK SELF _TSRANGE" => \&_method_lock_self_tsrange,

    # Priv commands
    "GET PRIV" => \&_method_priv,
    "PUT PRIV" => \&_method_priv,
    "POST PRIV" => \&_method_priv,
    "DELETE PRIV" => \&_method_priv,
    "GET PRIV EID _NUM" => \&_method_priv_eid_num,
    "PUT PRIV EID _NUM" => \&_method_priv_eid_num,
    "POST PRIV EID _NUM" => \&_method_priv_eid_num,
    "DELETE PRIV EID _NUM" => \&_method_priv_eid_num,
    "GET PRIV EID _NUM _TIMESTAMP" => \&_method_priv_eid_num_timestamp,
    "PUT PRIV EID _NUM _TIMESTAMP" => \&_method_priv_eid_num_timestamp, 
    "POST PRIV EID _NUM _TIMESTAMP" => \&_method_priv_eid_num_timestamp, 
    "DELETE PRIV EID _NUM _TIMESTAMP" => \&_method_priv_eid_num_timestamp,
    "GET PRIV HISTORY EID _NUM" => \&_method_priv_history_eid_num,
    "PUT PRIV HISTORY EID _NUM" => \&_method_priv_history_eid_num,
    "POST PRIV HISTORY EID _NUM" => \&_method_priv_history_eid_num,
    "DELETE PRIV HISTORY EID _NUM" => \&_method_priv_history_eid_num,
    "GET PRIV HISTORY EID _NUM _TSRANGE" => \&_method_priv_history_eid_num_tsrange,
    "PUT PRIV HISTORY EID _NUM _TSRANGE" => \&_method_priv_history_eid_num_tsrange,
    "POST PRIV HISTORY EID _NUM _TSRANGE" => \&_method_priv_history_eid_num_tsrange,
    "DELETE PRIV HISTORY EID _NUM _TSRANGE" => \&_method_priv_history_eid_num_tsrange,
    "GET PRIV HISTORY NICK _TERM" => \&_method_priv_history_nick_term,
    "PUT PRIV HISTORY NICK _TERM" => \&_method_priv_history_nick_term,
    "POST PRIV HISTORY NICK _TERM" => \&_method_priv_history_nick_term,
    "DELETE PRIV HISTORY NICK _TERM" => \&_method_priv_history_nick_term,
    "GET PRIV HISTORY NICK _TERM _TSRANGE" => \&_method_priv_history_nick_term_tsrange,
    "PUT PRIV HISTORY NICK _TERM _TSRANGE" => \&_method_priv_history_nick_term_tsrange,
    "POST PRIV HISTORY NICK _TERM _TSRANGE" => \&_method_priv_history_nick_term_tsrange,
    "DELETE PRIV HISTORY NICK _TERM _TSRANGE" => \&_method_priv_history_nick_term_tsrange,
    "GET PRIV HISTORY PHID _NUM" => \&_method_priv_history_phid_num,
    "PUT PRIV HISTORY PHID _NUM" => \&_method_priv_history_phid_num,
    "POST PRIV HISTORY PHID _NUM" => \&_method_priv_history_phid_num,
    "DELETE PRIV HISTORY PHID _NUM" => \&_method_priv_history_phid_num,
    "GET PRIV HISTORY SELF" => \&_method_priv_history_self,
    "PUT PRIV HISTORY SELF" => \&_method_priv_history_self,
    "POST PRIV HISTORY SELF" => \&_method_priv_history_self,
    "DELETE PRIV HISTORY SELF" => \&_method_priv_history_self,
    "GET PRIV HISTORY SELF _TSRANGE" => \&_method_priv_history_self_tsrange,
    "PUT PRIV HISTORY SELF _TSRANGE" => \&_method_priv_history_self_tsrange,
    "POST PRIV HISTORY SELF _TSRANGE" => \&_method_priv_history_self_tsrange,
    "DELETE PRIV HISTORY SELF _TSRANGE" => \&_method_priv_history_self_tsrange,
    "GET PRIV NICK _TERM" => \&_method_priv_nick_term,
    "PUT PRIV NICK _TERM" => \&_method_priv_nick_term,
    "POST PRIV NICK _TERM" => \&_method_priv_nick_term,
    "DELETE PRIV NICK _TERM" => \&_method_priv_nick_term,
    "GET PRIV NICK _TERM _TIMESTAMP" => \&_method_priv_nick_term_timestamp,
    "PUT PRIV NICK _TERM _TIMESTAMP" => \&_method_priv_nick_term_timestamp,
    "POST PRIV NICK _TERM _TIMESTAMP" => \&_method_priv_nick_term_timestamp,
    "DELETE PRIV NICK _TERM _TIMESTAMP" => \&_method_priv_nick_term_timestamp,
    "GET PRIV SELF" => \&_method_priv_self,
    "PUT PRIV SELF" => \&_method_priv_self,
    "POST PRIV SELF" => \&_method_priv_self,
    "DELETE PRIV SELF" => \&_method_priv_self,
    "GET PRIV SELF _TIMESTAMP" => \&_method_priv_self_timestamp,
    "PUT PRIV SELF _TIMESTAMP" => \&_method_priv_self_timestamp,
    "POST PRIV SELF _TIMESTAMP" => \&_method_priv_self_timestamp,
    "DELETE PRIV SELF _TIMESTAMP" => \&_method_priv_self_timestamp,

    # Schedule commands
    "GET SCHEDULE" => \&_method_schedule,
    "PUT SCHEDULE" => \&_method_schedule,
    "POST SCHEDULE" => \&_method_schedule,
    "DELETE SCHEDULE" => \&_method_schedule,
    "GET SCHEDULE ALL" => \&_method_schedule_all,
    "PUT SCHEDULE ALL" => \&_method_schedule_all,
    "POST SCHEDULE ALL" => \&_method_schedule_all,
    "DELETE SCHEDULE ALL" => \&_method_schedule_all,
    "GET SCHEDULE ALL DISABLED" => \&_method_schedule_all_disabled,
    "PUT SCHEDULE ALL DISABLED" => \&_method_schedule_all_disabled,
    "POST SCHEDULE ALL DISABLED" => \&_method_schedule_all_disabled,
    "DELETE SCHEDULE ALL DISABLED" => \&_method_schedule_all_disabled,
    "GET SCHEDULE EID _NUM" => \&_method_schedule_eid_num,
    "PUT SCHEDULE EID _NUM" => \&_method_schedule_eid_num,
    "POST SCHEDULE EID _NUM" => \&_method_schedule_eid_num,
    "DELETE SCHEDULE EID _NUM" => \&_method_schedule_eid_num,
    "GET SCHEDULE EID _NUM _TIMESTAMP" => \&_method_schedule_eid_num_timestamp,
    "PUT SCHEDULE EID _NUM _TIMESTAMP" => \&_method_schedule_eid_num_timestamp,
    "POST SCHEDULE EID _NUM _TIMESTAMP" => \&_method_schedule_eid_num_timestamp,
    "DELETE SCHEDULE EID _NUM _TIMESTAMP" => \&_method_schedule_eid_num_timestamp,
    "GET SCHEDULE HISTORY EID _NUM" => \&_method_schedule_history_eid_num,
    "PUT SCHEDULE HISTORY EID _NUM" => \&_method_schedule_history_eid_num,
    "POST SCHEDULE HISTORY EID _NUM" => \&_method_schedule_history_eid_num,
    "DELETE SCHEDULE HISTORY EID _NUM" => \&_method_schedule_history_eid_num,
    "GET SCHEDULE HISTORY EID _NUM _TSRANGE" => \&_method_schedule_history_eid_num_tsrange,
    "PUT SCHEDULE HISTORY EID _NUM _TSRANGE" => \&_method_schedule_history_eid_num_tsrange,
    "POST SCHEDULE HISTORY EID _NUM _TSRANGE" => \&_method_schedule_history_eid_num_tsrange,
    "DELETE SCHEDULE HISTORY EID _NUM _TSRANGE" => \&_method_schedule_history_eid_num_tsrange,
    "GET SCHEDULE HISTORY NICK _TERM" => \&_method_schedule_history_nick_term,
    "PUT SCHEDULE HISTORY NICK _TERM" => \&_method_schedule_history_nick_term,
    "POST SCHEDULE HISTORY NICK _TERM" => \&_method_schedule_history_nick_term,
    "DELETE SCHEDULE HISTORY NICK _TERM" => \&_method_schedule_history_nick_term,
    "GET SCHEDULE HISTORY NICK _TERM _TSRANGE" => \&_method_schedule_history_nick_term_tsrange,
    "PUT SCHEDULE HISTORY NICK _TERM _TSRANGE" => \&_method_schedule_history_nick_term_tsrange,
    "POST SCHEDULE HISTORY NICK _TERM _TSRANGE" => \&_method_schedule_history_nick_term_tsrange,
    "DELETE SCHEDULE HISTORY NICK _TERM _TSRANGE" => \&_method_schedule_history_nick_term_tsrange,
    "GET SCHEDULE HISTORY SELF" => \&_method_schedule_history_self,
    "PUT SCHEDULE HISTORY SELF" => \&_method_schedule_history_self,
    "POST SCHEDULE HISTORY SELF" => \&_method_schedule_history_self,
    "DELETE SCHEDULE HISTORY SELF" => \&_method_schedule_history_self,
    "GET SCHEDULE HISTORY SELF _TSRANGE" => \&_method_schedule_history_self_tsrange,
    "PUT SCHEDULE HISTORY SELF _TSRANGE" => \&_method_schedule_history_self_tsrange,
    "POST SCHEDULE HISTORY SELF _TSRANGE" => \&_method_schedule_history_self_tsrange,
    "DELETE SCHEDULE HISTORY SELF _TSRANGE" => \&_method_schedule_history_self_tsrange,
    "GET SCHEDULE HISTORY SHID _NUM" => \&_method_schedule_history_shid_num,
    "PUT SCHEDULE HISTORY SHID _NUM" => \&_method_schedule_history_shid_num,
    "POST SCHEDULE HISTORY SHID _NUM" => \&_method_schedule_history_shid_num,
    "DELETE SCHEDULE HISTORY SHID _NUM" => \&_method_schedule_history_shid_num,
    "GET SCHEDULE NICK _TERM" => \&_method_schedule_nick_term,
    "PUT SCHEDULE NICK _TERM" => \&_method_schedule_nick_term,
    "POST SCHEDULE NICK _TERM" => \&_method_schedule_nick_term,
    "DELETE SCHEDULE NICK _TERM" => \&_method_schedule_nick_term,
    "GET SCHEDULE NICK _TERM _TIMESTAMP" => \&_method_schedule_nick_term_timestamp,
    "PUT SCHEDULE NICK _TERM _TIMESTAMP" => \&_method_schedule_nick_term_timestamp,
    "POST SCHEDULE NICK _TERM _TIMESTAMP" => \&_method_schedule_nick_term_timestamp,
    "DELETE SCHEDULE NICK _TERM _TIMESTAMP" => \&_method_schedule_nick_term_timestamp,
    "GET SCHEDULE SCODE _TERM" => \&_method_schedule_scode_term,
    "PUT SCHEDULE SCODE _TERM" => \&_method_schedule_scode_term,
    "POST SCHEDULE SCODE _TERM" => \&_method_schedule_scode_term,
    "DELETE SCHEDULE SCODE _TERM" => \&_method_schedule_scode_term,
    "GET SCHEDULE SELF" => \&_method_schedule_self,
    "PUT SCHEDULE SELF" => \&_method_schedule_self,
    "POST SCHEDULE SELF" => \&_method_schedule_self,
    "DELETE SCHEDULE SELF" => \&_method_schedule_self,
    "GET SCHEDULE SELF _TIMESTAMP" => \&_method_schedule_self_timestamp,
    "PUT SCHEDULE SELF _TIMESTAMP" => \&_method_schedule_self_timestamp,
    "POST SCHEDULE SELF _TIMESTAMP" => \&_method_schedule_self_timestamp,
    "DELETE SCHEDULE SELF _TIMESTAMP" => \&_method_schedule_self_timestamp,
    "GET SCHEDULE SID _NUM" => \&_method_schedule_sid_num,
    "PUT SCHEDULE SID _NUM" => \&_method_schedule_sid_num,
    "POST SCHEDULE SID _NUM" => \&_method_schedule_sid_num,
    "DELETE SCHEDULE SID _NUM" => \&_method_schedule_sid_num,
    "GET SCHEDULE NEW" => \&_method_schedule_new,
    "PUT SCHEDULE NEW" => \&_method_schedule_new,
    "POST SCHEDULE NEW" => \&_method_schedule_new,
    "DELETE SCHEDULE NEW" => \&_method_schedule_new,

    # Activity commands
    "ACTIVITY" => \&activity_all,
    "ACTIVITY ALL" => \&activity_all,
    "ACTIVITY ALL DISABLED" => \&activity_all,
    
    # Report commands
    #"COMPONENT PATH _PATH" => \&component_path,

lib/App/Dochazka/CLI/Commands/Employee.pm  view on Meta::CPAN

    print "Entering " . __PACKAGE__ . "::employee_ldap_import\n" if $debug_mode;
    my ( $ts, $th ) = @_;

    # parse test
    return parse_test( $ts, $th ) if $ts eq 'PARSE_TEST';

    # determine nick
    my ( $nick ) = $th->{'EMPLOYEE_SPEC'} =~ m/=(.+)$/;

    # send the request
    my $status = send_req( 'PUT', "employee/nick/$nick/ldap" );
    if ( $status->level eq 'OK' and $status->code eq 'DOCHAZKA_CUD_OK' ) {
        return employee_profile( $ts, $th );
    } else {
        return $status;
    }
}

    
=head3 employee_list

lib/App/Dochazka/CLI/Commands/Employee.pm  view on Meta::CPAN

        print "\n";
    }
    ReadMode ('noecho');
    print "New password again: ";
    chomp( my $confirm = <> );
    ReadMode ('restore');
    print "\n";
    return $CELL->status_err( 'DOCHAZKA_CLI_NO_MATCH' ) unless $newpass eq $confirm;

    # send REST request
    my $status = send_req( 'PUT', "employee/eid/$eid", <<"EOS" );
{ "password" : "$newpass" }
EOS

    return $status unless $status->ok;
    return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION', 
        payload => "Password changed" );
}


=head3 _display_employee_ok

lib/App/Dochazka/CLI/Commands/Schedule.pm  view on Meta::CPAN

    
    # parse test
    return parse_test( $ts, $th ) if $ts eq 'PARSE_TEST';

    my ( $key_spec, $key ) = $th->{'SCHEDULE_SPEC'} =~ m/^(.*)\=(.*)$/;
    my $remark = $th->{'_REST'};
    $remark =~ s/\"/\'/g;

    my $status;
    if ( $key_spec =~ m/^sco/i ) {
        $status = send_req( 'PUT', "schedule/scode/$key", <<"EOS" );
{ "remark" : "$remark" }
EOS
    } elsif ( $key_spec =~ m/^sid/ ) {
        $status = send_req( 'PUT', "schedule/sid/$key", <<"EOS" );
{ "remark" : "$remark" }
EOS
    } else {
        die "AAAHAAAHHH!!! Invalid schedule lookup key " . ( defined( $key_spec ) ? $key_spec : "undefined" )
    }

    if ( $status->level eq 'OK' and $status->code eq 'DOCHAZKA_CUD_OK' ) {
        my $sch_obj = App::Dochazka::Common::Model::Schedule->spawn( %{ $status->payload } );
        my $pl = print_schedule_object( $sch_obj );
        return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION', payload => $pl );

lib/App/Dochazka/CLI/Commands/Schedule.pm  view on Meta::CPAN

    my ( $ts, $th ) = @_;
    
    # parse test
    return parse_test( $ts, $th ) if $ts eq 'PARSE_TEST';

    my ( $key_spec, $key ) = $th->{'SCHEDULE_SPEC'} =~ m/^(.*)\=(.*)$/;
    my $scode = $th->{'_TERM'};

    my $status;
    if ( $key_spec =~ m/^sco/i ) {
        $status = send_req( 'PUT', "schedule/scode/$key", <<"EOS" );
{ "scode" : "$scode" }
EOS
    } elsif ( $key_spec =~ m/^sid/ ) {
        $status = send_req( 'PUT', "schedule/sid/$key", <<"EOS" );
{ "scode" : "$scode" }
EOS
    } else {
        die "AAAHAAAHHH!!! Invalid schedule lookup key " . ( defined( $key_spec ) ? $key_spec : "undefined" )
    }

    if ( $status->level eq 'OK' and $status->code eq 'DOCHAZKA_CUD_OK' ) {
        my $sch_obj = App::Dochazka::Common::Model::Schedule->spawn( %{ $status->payload } );
        my $pl = print_schedule_object( $sch_obj );
        return $CELL->status_ok( 'DOCHAZKA_CLI_NORMAL_COMPLETION', payload => $pl );

lib/App/Dochazka/CLI/Guide.pm  view on Meta::CPAN


=back


=head2 Commands for generating HTTP requests

The CLI enables the user to generate HTTP requests to an L<App::Dochazka::REST>
server and view the server's responses. Commands in this category -- also known
as "REST test" commands -- have a direct correlation with the REST server
resources, always starting with one of the four basic HTTP methods supported by
the REST server: C<GET>, C<PUT>, C<POST>, C<DELETE>. These commands
are useful mainly for Dochazka developers, but may also be used by
administrators and normal users -- e.g., for troubleshooting and ad hoc
testing, or for doing things that the "normal" commands do not support. A "best
effort" has been made to support all the REST resources.

Commands in this category start with the HTTP method and continue 
with the resource (except it is written with spaces instead of forward
slashes) and concludes with the request entity, if any.

All CLI commands must be written on a single line of input, and

lib/App/Dochazka/CLI/Guide.pm  view on Meta::CPAN


    ACTIVITY ALL DISABLED

Displays a list of B<all> activities, including disabled activities.


=head3 Add a new activity

From time to time, new activities will need to be added:

    PUT activity code $CODE { "long_desc" : "activity description here" }

Optionally, a "remark" property can be included as well.


=head3 Disable an activity

To accomplish this, we can use a REST test command:

    PUT activity aid $AID { "disabled" : "t" }
    PUT activity code $CODE { "disabled" : "t" }

=head3 Re-enable an activity

To accomplish this, we can use a REST test command:

    PUT activity aid $AID { "disabled" : "f" }
    PUT activity code $CODE { "disabled" : "f" }

=head3 Delete an activity

Assuming nothing points to it, an activity can be deleted:

    DELETE activity aid $AID
    DELETE activity code $CODE


=head2 Employees

lib/App/Dochazka/CLI/Guide.pm  view on Meta::CPAN

Only nicks are shown, in alphabetical order.


=head3 Create a new employee 

If you are using LDAP authentication, your employees are in the LDAP database
and you can turn on DOCHAZKA_LDAP_AUTOCREATE. Then employees will be created
automatically the first time they log in. Alternatively, employees can be
created manually:

    PUT employee nick $NICK { "fullname" : "King George III" }

In addition to "fullname", the following properties can be specified inside
the curly brackets:

    sec_id
    email
    password
    remark

For example, to add an employee with nick 'nancy' the command might look like
this:

    PUT employee nick nancy { "fullname" : "Nancy Bright Red", "email" : "nancy@identity.org" }
   
The new employee will have passerby privileges only until a privhistory record
is created (see L<"Add privilege history record">, below).


=head3 Set employee secondary ID

To manually change an employee's secondary ID, do one of the following:

    EMPLOYEE_SPEC SEC_ID $SEC_ID

lib/App/Dochazka/CLI/Guide.pm  view on Meta::CPAN

    SCHEDULE_SPEC SCODE $REMARK
    SCHEDULE_SPEC SET SCODE $REMARK

The scode may contain only ASCII letters, numerals, underscores, and hyphens.


=head3 Disable a schedule

Assuming we know the SID or scode of the schedule, we can disable it:

    PUT SCHEDULE SID $SID { "disabled" : "t" }
    PUT SCHEDULE SCODE $SCODE { "disabled" : "t" }


=head3 Re-enable a schedule

To re-enable a disabled schedule:

    PUT SCHEDULE SID $SID { "disabled" : "f" }
    PUT SCHEDULE SCODE $SCODE { "disabled" : "f" }


=head2 Histories

Maintaining/updating employee history records (recording changes in privilege
level and schedule, primarily) is a typical administrator workflow.


=head3 Add privilege history record

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN

    *** Anomaly detected ***
    Status:      403 Forbidden
    Explanation: ACL check failed for resource employee/list/?:priv (ERR)

This output indicates that the REST server returned a C<403 Forbidden> error,
which is to be expected because the C<demo> employee has insufficient
privileges.

Next, try to create an employee:

    Dochazka(2016-01-12) demo PASSERBY> PUT employee nick george { "fullname" : "King George III" }
    HTTP status: 403 Forbidden
    Non-suppressed headers: {
      'X-Web-Machine-Trace' => 'b13,b12,b11,b10,b9,b8,b7'
    }
    Response:
    {
       "payload" : {
          "http_code" : 403,
          "uri_path" : "employee/nick/george",
          "permanent" : true,
          "found_in" : {
             "file" : "/usr/lib/perl5/vendor_perl/5.22.0/App/Dochazka/REST/Auth.pm",
             "package" : "App::Dochazka::REST::Auth",
             "line" : 431
          },
          "resource_name" : "employee/nick/:nick",
          "http_method" : "PUT"
       },
       "text" : "ACL check failed for resource employee/nick/:nick",
       "level" : "ERR",
       "code" : "DISPATCH_ACL_CHECK_FAILED"
    }

Here, the error is the same C<403 Forbidden> but the output is more detailed.
This is because we used a special type of command that is ordinarily only
used to test the REST API.

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN

listed, regardless of their priv level.

You can also try listing employees by priv level as per the documentation.

=head2 Create an employee

At the moment there is no CLI command to create a new employee. Hence we use
the REST API testing command as described in
L<App::Dochazka::CLI::Guide|"Create a new employee">:

    Dochazka(2016-01-12) root ADMIN> PUT employee nick george { "fullname" : "King George III" }
    HTTP status: 200 OK
    Non-suppressed headers: {
      'X-Web-Machine-Trace' => 'b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,c3,c4,d4,e5,f6,g7,g8,h10,i12,l13,m16,n16,o16,o14,p11,o20,o18,o18b'
    }
    Response:
    {
       "code" : "DOCHAZKA_CUD_OK",
       "count" : 1,
       "payload" : {
          "email" : null,

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN


=head2 Verify state

If you are continuing from Session 1, you can skip this step.

If you are starting over (or from scratch), run the following script to
bring your database into the proper state:

    #!/bin/sh
    cat <<EOF | dochazka-cli -u root -p immutable
    PUT employee nick george { "fullname" : "King George III" }
    EOF


=head2 View employee profile

Let us see the state of a freshly created employee:

    Dochazka(2016-01-27) root ADMIN> emp=george profile

    Full name:    King George III

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN


=head2 Verify state

If you are continuing from Session 2, you can skip this step.

If you are starting over (or from scratch), run the following script to
bring your database into the proper state:

    #!/bin/sh
    cat <<EOF | dochazka-cli -u root -p immutable
    PUT employee nick george { "fullname" : "King George III", "salt" : "a054d158a23c3a07ad0163107ad72a8649597d71", "passhash" : "5cf2c3a23de9db43d2d846172966150e9197717ecd0304bafef3f23fc159df942021dd3aec7b4dbcde87d8a44c1bd905bbba3862989065d012bb46a1...
    EOF


=head2 Log in as the test employee

This just demonstrates that the test employee can log in.

    $ dochazka-cli -u george -p george
    ...
    Authenticating to server at http://localhost:5000 as user george

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN


=head2 Verify state

If you are continuing from Session 3, you can skip this step.

If you are starting over (or from scratch), run the following script to
bring your database into the proper state:

    #!/bin/sh
    cat <<EOF | dochazka-cli -u root -p immutable
    PUT employee nick george { "fullname" : "King George III", "salt" : "a054d158a23c3a07ad0163107ad72a8649597d71", "passhash" : "5cf2c3a23de9db43d2d846172966150e9197717ecd0304bafef3f23fc159df942021dd3aec7b4dbcde87d8a44c1bd905bbba3862989065d012bb46a1...
    emp=george active 2015-01-02
    EOF


=head2 Try to enter an attendance interval

At this point, one might be tempted to start entering attendance intervals,
so let's give it a try:

    Dochazka(2016-01-29) george ACTIVE> interval 8:00-9:00 work Pushing pencils

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN


=head2 Verify state

If you are continuing from Session 4, you can skip this step.

If you are starting over (or from scratch), run the following script to
bring your database into the proper state:

    #!/bin/sh
    cat <<EOF | dochazka-cli -u root -p immutable
    PUT employee nick george { "fullname" : "King George III", "salt" :
    "a054d158a23c3a07ad0163107ad72a8649597d71", "passhash" :
    "5cf2c3a23de9db43d2d846172966150e9197717ecd0304bafef3f23fc159df942021dd3aec7b4dbcde87d8a44c1bd905bbba3862989065d012bb46a1e2b9ac5c"
    }
    emp=george active 2015-01-02
    schedule mon 8:00-12:00
    schedule tue 13:00-17:00
    schedule wed 8:00-12:00
    schedule wed 13:00-17:00
    schedule thu 7:00-10:00
    schedule scode VPP-1

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN


=head2 Verify state

If you are continuing from Session 5, you can skip this step.

If you are starting over (or from scratch), run the following script to
bring your database into the proper state:

    #!/bin/sh
    cat <<EOF | dochazka-cli -u root -p immutable
    PUT employee nick george { "fullname" : "King George III", "salt" : "a054d158a23c3a07ad0163107ad72a8649597d71", "passhash" : "5cf2c3a23de9db43d2d846172966150e9197717ecd0304bafef3f23fc159df942021dd3aec7b4dbcde87d8a44c1bd905bbba3862989065d012bb46a1...
    emp=george active 2015-01-02
    schedule mon 8:00-12:00
    schedule tue 13:00-17:00
    schedule wed 8:00-12:00
    schedule wed 13:00-17:00
    schedule thu 7:00-10:00
    schedule scode VPP-1
    schedule new
    emp=george scode=VPP-1 2015-01-02
    EOF

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN


    Dochazka(2016-02-02) root ADMIN> get param site DOCHAZKA_ACTIVITY_DEFINITIONS
    ...


=head2 Create a new activity

Since this is not expected to be a frequent operation, no special command
has been implemented. We use the REST resource directly:

    Dochazka(2016-02-02) root ADMIN> PUT activity code TESTACT { "long_desc" : "testing" }
    HTTP status: 200 OK
    ...
    Response:
    {  
       "payload" : {
          "disabled" : 0,
          "code" : "TESTACT",
          "aid" : 9,
          "remark" : null,
          "long_desc" : "testing"

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN

    ...


=head2 Disable an activity

In the course of events, it might happen that an activity becomes obsolete or
deprecated. If there are no attendance intervals associated with it, it can be
deleted outright. This is probably not the case, but we can still cause the 
activity to disappear from the listing by disabling it:

    Dochazka(2016-02-02) root ADMIN> PUT activity code TESTACT { "disabled" : "t" }
    HTTP status: 200 OK
    ...

Now, it's gone from the list:

    Dochazka(2016-02-02) root ADMIN> activity all
    ...

List all activites B<including> disabled ones:

    Dochazka(2016-02-02) root ADMIN> activity all disabled
    ...

Now, re-enable TESTACT:

    Dochazka(2016-02-02) root ADMIN> PUT activity code TESTACT { "disabled" : "f" }
    HTTP status: 200 OK
    ...

It's back:

    Dochazka(2016-02-02) root ADMIN> activity all
    ...


=head2 Modify an activity

Activities can be modified. 

    Dochazka(2016-02-02) root ADMIN> PUT activity aid 9 { "remark" : "Bike shed" }
    ...

See the effects:

    Dochazka(2016-02-02) root ADMIN> GET activity aid 9
    ...

For fun, try out various silly ideas:

    Dochazka(2016-02-02) root ADMIN> PUT activity aid 9 { "code" : "Bikeshed" }
    ...
    Dochazka(2016-02-02) root ADMIN> PUT activity aid 9 { "code" : "Bike shed" }
    ...
    Dochazka(2016-02-02) root ADMIN> PUT activity aid 9 { "aid" : 100 }
    ...
    Dochazka(2016-02-02) root ADMIN> PUT activity aid 9 { "aid" : null }
    ...
    Dochazka(2016-02-02) root ADMIN> PUT activity aid 9 { "remark" : null }
    ...


=head2 Delete an activity

OK, now we've had our fun. Delete this fiasco and get back to work!

    Dochazka(2016-02-02) root ADMIN> DELETE activity aid 9
    ... 

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN


=head2 Verify state

If you are continuing from Session 6, you can skip this step.

If you are starting over (or from scratch), run the following script to
bring your database into the proper state:

    #!/bin/sh
    cat <<EOF | dochazka-cli -u root -p immutable
    PUT employee nick george { "fullname" : "King George III", "salt" : "a054d158a23c3a07ad0163107ad72a8649597d71", "passhash" : "5cf2c3a23de9db43d2d846172966150e9197717ecd0304bafef3f23fc159df942021dd3aec7b4dbcde87d8a44c1bd905bbba3862989065d012bb46a1...
    emp=george active 2015-01-02
    schedule mon 8:00-12:00
    schedule tue 13:00-17:00
    schedule wed 8:00-12:00
    schedule wed 13:00-17:00
    schedule thu 7:00-10:00
    schedule scode VPP-1
    schedule new
    emp=george scode=VPP-1 2015-01-02
    EOF

lib/App/Dochazka/CLI/Testers.pm  view on Meta::CPAN

The attributes under the "payload" are from the interval object. The "code"
attribute is null in this case because it is not stored in the database. It is
populated on an as-needed basis.


=head2 Modify an interval

We can modify intervals in the same way that we modified the "bike shed"
activity:

    Dochazka(2016-02-03) george ACTIVE> PUT interval iid 1 { "remark" : "BIKESHED" }
    ...

We can even set the "code" attribute to a bogus value in this way:

    Dochazka(2016-02-03) george ACTIVE> PUT interval iid 1 { "code" : "BIKESHED" }
    ...

It does not get stored in the database, however:

    Dochazka(2016-02-03) george ACTIVE> GET interval iid 1 { "code" : "BIKESHED" }
    HTTP status: 200 OK
    Response:
    ...
          "code" : null,
    ...

lib/App/Dochazka/CLI/TokenMap.pm  view on Meta::CPAN

    PASSWORD  => '(passw\S*)',
    PATH      => '(pat\S*)',
    PHID      => '(phi[^\s=]*)',
    PHISTORY_SPEC => 'phi[^\s=]*=(\d+)',
    POD       => '(pod\S*)',
    POST      => '(pos\S*)',
    PRIV      => '(pri\S*)',
    PRIV_SPEC  => '((active)|(adm\S*)|(ina\S*)|(passe\S*))',
    PROFILE   => '(prof\S*)',
    PROMPT    => '(prom\S*)',
    PUT       => '(put\S*)',
    REMARK    => '(rem\S*)',
    REPORT    => '(rep\S*)',
#    SATURDAY    => '(sat\S*)',  RESERVED BY _DOW
    SCHEDULE  => '(sch\S*)',
    SCHEDULE_SPEC => '((sco|sid)[^\s=]*=([%[:alnum:]_][%[:alnum:]_-]*)*)',
    SCODE     => '(sco[^\s=]*)',
    SEARCH    => '(sea\S*)',
    SEC_ID    => '(sec[^\s=]*)',
    SELF      => '(sel\S*)',
#    SEPTEMBER => '(sep\S*)',

lib/App/Dochazka/CLI/TokenMap.pm  view on Meta::CPAN

    passerby => 'PRIV_SPEC',
    password => 'PASSWORD',
    path => 'PATH',
    phid => 'PHID',
    'phid=' => 'PHISTORY_SPEC',
    pod => 'POD',
    post => 'POST',
    priv => 'PRIV',
    profile => 'PROFILE',
    prompt => 'PROMPT',
    put => 'PUT',
    quit => 'QUIT',
    remark => 'REMARK',
    report => 'REPORT',
    saturday => '_DOW',
    schedule => 'SCHEDULE',
    scode => 'SCODE',
    'scode=' => 'SCHEDULE_SPEC',
    search => 'SEARCH',
    sec_id => 'SEC_ID',
    'sec_id=' => 'EMPLOYEE_SPEC',

t/001-init.t  view on Meta::CPAN

sub create_employees_carefully {
    my ( $nick, $privlevel, $fullname ) = @_;
    my ( $cmd, $rv, $status );

    $cmd = "EMPLOYEE=$nick PROFILE";
    $rv = process_command( $cmd );
    is( ref( $rv ), 'App::CELL::Status' );
    unless ( $rv->level eq 'OK' and $rv->code eq 'DOCHAZKA_CLI_NORMAL_COMPLETION' ) {

        # create employee $nick and assign privlevel $privlevel
        $cmd = "PUT employee nick $nick { \"fullname\" : \"$fullname\", \"password\" : \"$nick\" }";
        $rv = process_command( $cmd );
        is( ref( $rv ), 'App::CELL::Status' );
        is( $rv->{'http_status'}, '200 OK' );
        is( $rv->code, 'DOCHAZKA_CUD_OK' );

        $cmd = "POST priv history nick $nick { \"priv\" : \"$privlevel\", \"effective\" : \"2000-01-01 00:00\" }";
        $rv = process_command( $cmd );
        is( ref( $rv ), 'App::CELL::Status' );
        is( $rv->{'http_status'}, '201 Created' );
        is( $rv->code, 'DOCHAZKA_CUD_OK' );

t/cmd_admin/employee-utf8.t  view on Meta::CPAN

plan skip_all => "init_unit failed with status " . $rv->text unless $rv->ok;

$rv = authenticate_to_server( user => 'root', password => 'immutable', quiet => 1 );
if ( $rv->not_ok and $rv->{'http_status'} =~ m/500 Can\'t connect/ ) {
    plan skip_all => "Can't connect to server";
}

isnt( $meta->MREST_CLI_URI_BASE, undef, 'MREST_CLI_URI_BASE is defined after initialization' );

note( 'Create testing employee with UTF-8 characters' );
$cmd = "PUT employee nick george { \"fullname\" : \"Karel Omáčka\" }";
$rv = process_command( $cmd );
ok( ref( $rv ) eq 'App::CELL::Status' );
ok( $rv->ok );
is( $rv->code, 'DOCHAZKA_CUD_OK' );
is( $rv->payload->{'nick'}, 'george' );
is( $rv->payload->{'fullname'}, "Karel Om\x{e1}\x{10d}ka" );

note( 'EMP=george PROFILE to test UTF-8 handling' );
$cmd = "EMP=george PROFILE";
$rv = process_command( $cmd );

t/parser/rest_test.t  view on Meta::CPAN

is( $res->{th}->{_DOCU}, "\"activity/eid/:eid\"" );

#
# systematic tests
#

my %map = (

    # Top-level commands
    'GET' => [ 'GET', '' ],
    'PUT' => [ 'PUT', '' ],
    'POST' => [ 'POST', '' ],
    'DELETE' => [ 'DELETE', '' ],
    "GET BUGREPORT" => [ 'GET', 'bugreport' ],
    "PUT BUGREPORT" => [ 'PUT', 'bugreport' ],
    "POST BUGREPORT" => [ 'POST', 'bugreport' ],
    "DELETE BUGREPORT" => [ 'DELETE', 'bugreport' ],
#    "GET COOKIEJAR" => [ 'GET', 'cookiejar' ],
#    "PUT COOKIEJAR" => [ 'PUT', 'cookiejar' ],
#    "POST COOKIEJAR" => [ 'POST', 'cookiejar' ],
#    "DELETE COOKIEJAR" => [ 'DELETE', 'cookiejar' ],
    "GET DBSTATUS" => [ 'GET', 'dbstatus' ],
    "PUT DBSTATUS" => [ 'PUT', 'dbstatus' ],
    "POST DBSTATUS" => [ 'POST', 'dbstatus' ],
    "DELETE DBSTATUS" => [ 'DELETE', 'dbstatus' ],
    "GET DOCU" => [ 'GET', 'docu' ],
    "PUT DOCU" => [ 'PUT', 'docu' ],
    "POST DOCU" => [ 'POST', 'docu' ],
    "DELETE DOCU" => [ 'DELETE', 'docu' ],
    "GET DOCU POD" => [ 'GET', 'docu/pod' ],
    "PUT DOCU POD" => [ 'PUT', 'docu/pod' ],
    "POST DOCU POD" => [ 'POST', 'docu/pod' ],
    "DELETE DOCU POD" => [ 'DELETE', 'docu/pod' ],
    "GET DOCU HTML" => [ 'GET', 'docu/html' ],
    "PUT DOCU HTML" => [ 'PUT', 'docu/html' ],
    "POST DOCU HTML" => [ 'POST', 'docu/html' ],
    "DELETE DOCU HTML" => [ 'DELETE', 'docu/html' ],
    "GET DOCU TEXT" => [ 'GET', 'docu/text' ],
    "PUT DOCU TEXT" => [ 'PUT', 'docu/text' ],
    "POST DOCU TEXT" => [ 'POST', 'docu/text' ],
    "DELETE DOCU TEXT" => [ 'DELETE', 'docu/text' ],
    "GET ECHO" => [ 'GET', 'echo' ],
    "PUT ECHO" => [ 'PUT', 'echo' ],
    "POST ECHO" => [ 'POST', 'echo' ],
    "DELETE ECHO" => [ 'DELETE', 'echo' ],
    "GET FORBIDDEN" => [ 'GET', 'forbidden' ],
    "PUT FORBIDDEN" => [ 'PUT', 'forbidden' ],
    "POST FORBIDDEN" => [ 'POST', 'forbidden' ],
    "DELETE FORBIDDEN" => [ 'DELETE', 'forbidden' ],
    "GET NOOP" => [ 'GET', 'noop' ],
    "PUT NOOP" => [ 'PUT', 'noop' ],
    "POST NOOP" => [ 'POST', 'noop' ],
    "DELETE NOOP" => [ 'DELETE', 'noop' ],
    "GET PARAM" => [ 'GET', 'param' ],
    "PUT PARAM" => [ 'PUT', 'param' ],
    "POST PARAM" => [ 'POST', 'param' ],
    "DELETE PARAM" => [ 'DELETE', 'param' ],
    "GET PARAM CORE FOOBAR" => [ 'GET', 'param/core/FOOBAR' ],
    "PUT PARAM CORE FOOBAR" => [ 'PUT', 'param/core/FOOBAR' ], 
    "POST PARAM CORE FOOBAR" => [ 'POST', 'param/core/FOOBAR' ],
    "DELETE PARAM CORE FOOBAR" => [ 'DELETE', 'param/core/FOOBAR' ],
    "GET PARAM META FOOBAR" => [ 'GET', 'param/meta/FOOBAR' ],
    "PUT PARAM META FOOBAR" => [ 'PUT', 'param/meta/FOOBAR' ], 
    "POST PARAM META FOOBAR" => [ 'POST', 'param/meta/FOOBAR' ],
    "DELETE PARAM META FOOBAR" => [ 'DELETE', 'param/meta/FOOBAR' ],
    "GET PARAM SITE FOOBAR" => [ 'GET', 'param/site/FOOBAR' ],
    "PUT PARAM SITE FOOBAR" => [ 'PUT', 'param/site/FOOBAR' ], 
    "POST PARAM SITE FOOBAR" => [ 'POST', 'param/site/FOOBAR' ],
    "DELETE PARAM SITE FOOBAR" => [ 'DELETE', 'param/site/FOOBAR' ],
    "GET SESSION" => [ 'GET', 'session' ],
    "PUT SESSION" => [ 'PUT', 'session' ],
    "POST SESSION" => [ 'POST', 'session' ],
    "DELETE SESSION" => [ 'DELETE', 'session' ],
    "GET VERSION" => [ 'GET', 'version' ],
    "PUT VERSION" => [ 'PUT', 'version' ],
    "POST VERSION" => [ 'POST', 'version' ],
    "DELETE VERSION" => [ 'DELETE', 'version' ],
    "GET WHOAMI" => [ 'GET', 'whoami' ],
    "PUT WHOAMI" => [ 'PUT', 'whoami' ],
    "POST WHOAMI" => [ 'POST', 'whoami' ],
    "DELETE WHOAMI" => [ 'DELETE', 'whoami' ],
    
    # Activity commands
    "GET ACTIVITY AID 123" => [ 'GET', 'activity/aid/123' ],
    "PUT ACTIVITY AID 123" => [ 'PUT', 'activity/aid/123' ],
    "POST ACTIVITY AID 123" => [ 'POST', 'activity/aid/123' ],
    "DELETE ACTIVITY AID 123" => [ 'DELETE', 'activity/aid/123' ],
    "GET ACTIVITY ALL" => [ 'GET', 'activity/all' ],
    "PUT ACTIVITY ALL" => [ 'PUT', 'activity/all' ],
    "POST ACTIVITY ALL" => [ 'POST', 'activity/all' ],
    "DELETE ACTIVITY ALL" => [ 'DELETE', 'activity/all' ],
    "GET ACTIVITY ALL DISABLED" => [ 'GET', 'activity/all/disabled' ],
    "PUT ACTIVITY ALL DISABLED" => [ 'PUT', 'activity/all/disabled' ],
    "POST ACTIVITY ALL DISABLED" => [ 'POST', 'activity/all/disabled' ],
    "DELETE ACTIVITY ALL DISABLED" => [ 'DELETE', 'activity/all/disabled' ],
    "GET ACTIVITY CODE FOOBAR" => [ 'GET', 'activity/code/FOOBAR' ],
    "PUT ACTIVITY CODE FOOBAR" => [ 'PUT', 'activity/code/FOOBAR' ],
    "POST ACTIVITY CODE FOOBAR" => [ 'POST', 'activity/code/FOOBAR' ],
    "DELETE ACTIVITY CODE FOOBAR" => [ 'DELETE', 'activity/code/FOOBAR' ],

    # Employee commands
    "GET EMPLOYEE" => [ 'GET', 'employee' ],
    "PUT EMPLOYEE" => [ 'PUT', 'employee' ],
    "POST EMPLOYEE" => [ 'POST', 'employee' ],
    "DELETE EMPLOYEE" => [ 'DELETE', 'employee' ],
    "GET EMPLOYEE COUNT" => [ 'GET', 'employee/count' ],
    "PUT EMPLOYEE COUNT" => [ 'PUT', 'employee/count' ],
    "POST EMPLOYEE COUNT" => [ 'POST', 'employee/count' ],
    "DELETE EMPLOYEE COUNT" => [ 'DELETE', 'employee/count' ],
    "GET EMPLOYEE COUNT PRIV" => [ 'GET', 'employee/count/priv' ],
    "PUT EMPLOYEE COUNT PRIV" => [ 'PUT', 'employee/count/priv' ],
    "POST EMPLOYEE COUNT PRIV" => [ 'POST', 'employee/count/priv' ],
    "DELETE EMPLOYEE COUNT PRIV" => [ 'DELETE', 'employee/count/priv' ],
    "GET EMPLOYEE SEARCH" => [ 'GET', 'employee/search' ],
    "PUT EMPLOYEE SEARCH" => [ 'PUT', 'employee/search' ],
    "POST EMPLOYEE SEARCH" => [ 'POST', 'employee/search' ],
    "DELETE EMPLOYEE SEARCH" => [ 'DELETE', 'employee/search' ],
    "GET EMPLOYEE SEARCH NICK foobar" => [ 'GET', 'employee/search/nick/foobar' ],
    "PUT EMPLOYEE SEARCH NICK foobar" => [ 'PUT', 'employee/search/nick/foobar' ],
    "POST EMPLOYEE SEARCH NICK foobar" => [ 'POST', 'employee/search/nick/foobar' ],
    "DELETE EMPLOYEE SEARCH NICK foobar" => [ 'DELETE', 'employee/search/nick/foobar' ],
    "GET EMPLOYEE SELF" => [ 'GET', 'employee/self' ],
    "PUT EMPLOYEE SELF" => [ 'PUT', 'employee/self' ],
    "POST EMPLOYEE SELF" => [ 'POST', 'employee/self' ],
    "DELETE EMPLOYEE SELF" => [ 'DELETE', 'employee/self' ],
    "GET EMPLOYEE SELF FULL" => [ 'GET', 'employee/self/full' ],
    "PUT EMPLOYEE SELF FULL" => [ 'PUT', 'employee/self/full' ],
    "POST EMPLOYEE SELF FULL" => [ 'POST', 'employee/self/full' ],
    "DELETE EMPLOYEE SELF FULL" => [ 'DELETE', 'employee/self/full' ],
    "GET EMPLOYEE EID" => [ 'GET', 'employee/eid' ],
    "PUT EMPLOYEE EID" => [ 'PUT', 'employee/eid' ],
    "POST EMPLOYEE EID" => [ 'POST', 'employee/eid' ],
    "DELETE EMPLOYEE EID" => [ 'DELETE', 'employee/eid' ],
    "GET EMPLOYEE EID 1" => [ 'GET', 'employee/eid/1' ],
    "PUT EMPLOYEE EID 1" => [ 'PUT', 'employee/eid/1' ],
    "POST EMPLOYEE EID 1" => [ 'POST', 'employee/eid/1' ],
    "DELETE EMPLOYEE EID 1" => [ 'DELETE', 'employee/eid/1' ],
    "GET EMPLOYEE NICK" => [ 'GET', 'employee/nick' ],
    "PUT EMPLOYEE NICK" => [ 'PUT', 'employee/nick' ],
    "POST EMPLOYEE NICK" => [ 'POST', 'employee/nick' ],
    "DELETE EMPLOYEE NICK" => [ 'DELETE', 'employee/nick' ],
    "GET EMPLOYEE NICK FOOBAR" => [ 'GET', 'employee/nick/FOOBAR' ],
    "PUT EMPLOYEE NICK FOOBAR" => [ 'PUT', 'employee/nick/FOOBAR' ],
    "POST EMPLOYEE NICK FOOBAR" => [ 'POST', 'employee/nick/FOOBAR' ],
    "DELETE EMPLOYEE NICK FOOBAR" => [ 'DELETE', 'employee/nick/FOOBAR' ],

    # Interval commands
    "GET INTERVAL" => [ 'GET', 'interval' ],
    "PUT INTERVAL" => [ 'PUT', 'interval' ],
    "POST INTERVAL" => [ 'POST', 'interval' ],
    "DELETE INTERVAL" => [ 'DELETE', 'interval' ],
    "GET INTERVAL EID 123" => [ 'GET', 'interval/eid/123' ],
    "PUT INTERVAL EID 123" => [ 'PUT', 'interval/eid/123' ],
    "POST INTERVAL EID 123" => [ 'POST', 'interval/eid/123' ],
    "DELETE INTERVAL EID 123" => [ 'DELETE', 'interval/eid/123' ],
    "GET INTERVAL EID 123 [,)" => [ 'GET', 'interval/eid/123/[,)' ],
    "PUT INTERVAL EID 123 [,)" => [ 'PUT', 'interval/eid/123/[,)' ],
    "POST INTERVAL EID 123 [,)" => [ 'POST', 'interval/eid/123/[,)' ],
    "DELETE INTERVAL EID 123 [,)" => [ 'DELETE', 'interval/eid/123/[,)' ],
    "GET INTERVAL IID 123" => [ 'GET', 'interval/iid/123' ],
    "PUT INTERVAL IID 123" => [ 'PUT', 'interval/iid/123' ],
    "POST INTERVAL IID 123" => [ 'POST', 'interval/iid/123' ],
    "DELETE INTERVAL IID 123" => [ 'DELETE', 'interval/iid/123' ],
    "GET INTERVAL NEW" => [ 'GET', 'interval/new' ],
    "PUT INTERVAL NEW" => [ 'PUT', 'interval/new' ],
    "POST INTERVAL NEW" => [ 'POST', 'interval/new' ],
    "DELETE INTERVAL NEW" => [ 'DELETE', 'interval/new' ],
    "GET INTERVAL NICK 123" => [ 'GET', 'interval/nick/123' ],
    "PUT INTERVAL NICK 123" => [ 'PUT', 'interval/nick/123' ],
    "POST INTERVAL NICK 123" => [ 'POST', 'interval/nick/123' ],
    "DELETE INTERVAL NICK 123" => [ 'DELETE', 'interval/nick/123' ],
    "GET INTERVAL NICK 123 [,)" => [ 'GET', 'interval/nick/123/[,)' ],
    "PUT INTERVAL NICK 123 [,)" => [ 'PUT', 'interval/nick/123/[,)' ],
    "POST INTERVAL NICK 123 [,)" => [ 'POST', 'interval/nick/123/[,)' ],
    "DELETE INTERVAL NICK 123 [,)" => [ 'DELETE', 'interval/nick/123/[,)' ],
    "GET INTERVAL SELF" => [ 'GET', 'interval/self' ],
    "PUT INTERVAL SELF" => [ 'PUT', 'interval/self' ],
    "POST INTERVAL SELF" => [ 'POST', 'interval/self' ],
    "DELETE INTERVAL SELF" => [ 'DELETE', 'interval/self' ],
    'GET INTERVAL SELF [,)' => [ 'GET', 'interval/self/[,)' ],
    'PUT INTERVAL SELF [,)' => [ 'PUT', 'interval/self/[,)' ],
    'POST INTERVAL SELF [,)' => [ 'POST', 'interval/self/[,)' ],
    'DELETE INTERVAL SELF [,)' => [ 'DELETE', 'interval/self/[,)' ],
    'GET INTERVAL SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'GET', 'interval/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],
    'PUT INTERVAL SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'PUT', 'interval/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],
    'POST INTERVAL SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'POST', 'interval/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],
    'DELETE INTERVAL SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'DELETE', 'interval/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],

    # Lock commands
    "GET LOCK" => [ 'GET', 'lock' ],
    "PUT LOCK" => [ 'PUT', 'lock' ],
    "POST LOCK" => [ 'POST', 'lock' ],
    "DELETE LOCK" => [ 'DELETE', 'lock' ],
    "GET LOCK EID 123" => [ 'GET', 'lock/eid/123' ],
    "PUT LOCK EID 123" => [ 'PUT', 'lock/eid/123' ],
    "POST LOCK EID 123" => [ 'POST', 'lock/eid/123' ],
    "DELETE LOCK EID 123" => [ 'DELETE', 'lock/eid/123' ],
    "GET LOCK EID 123 [,)" => [ 'GET', 'lock/eid/123/[,)' ],
    "PUT LOCK EID 123 [,)" => [ 'PUT', 'lock/eid/123/[,)' ],
    "POST LOCK EID 123 [,)" => [ 'POST', 'lock/eid/123/[,)' ],
    "DELETE LOCK EID 123 [,)" => [ 'DELETE', 'lock/eid/123/[,)' ],
    "GET LOCK LID 123" => [ 'GET', 'lock/lid/123' ],
    "PUT LOCK LID 123" => [ 'PUT', 'lock/lid/123' ],
    "POST LOCK LID 123" => [ 'POST', 'lock/lid/123' ],
    "DELETE LOCK LID 123" => [ 'DELETE', 'lock/lid/123' ],
    "GET LOCK NEW" => [ 'GET', 'lock/new' ],
    "PUT LOCK NEW" => [ 'PUT', 'lock/new' ],
    "POST LOCK NEW" => [ 'POST', 'lock/new' ],
    "DELETE LOCK NEW" => [ 'DELETE', 'lock/new' ],
    "GET LOCK NICK 123" => [ 'GET', 'lock/nick/123' ],
    "PUT LOCK NICK 123" => [ 'PUT', 'lock/nick/123' ],
    "POST LOCK NICK 123" => [ 'POST', 'lock/nick/123' ],
    "DELETE LOCK NICK 123" => [ 'DELETE', 'lock/nick/123' ],
    "GET LOCK NICK 123 [,)" => [ 'GET', 'lock/nick/123/[,)' ],
    "PUT LOCK NICK 123 [,)" => [ 'PUT', 'lock/nick/123/[,)' ],
    "POST LOCK NICK 123 [,)" => [ 'POST', 'lock/nick/123/[,)' ],
    "DELETE LOCK NICK 123 [,)" => [ 'DELETE', 'lock/nick/123/[,)' ],
    "GET LOCK SELF" => [ 'GET', 'lock/self' ],
    "PUT LOCK SELF" => [ 'PUT', 'lock/self' ],
    "POST LOCK SELF" => [ 'POST', 'lock/self' ],
    "DELETE LOCK SELF" => [ 'DELETE', 'lock/self' ],
    'GET LOCK SELF [,)' => [ 'GET', 'lock/self/[,)' ],
    'PUT LOCK SELF [,)' => [ 'PUT', 'lock/self/[,)' ],
    'POST LOCK SELF [,)' => [ 'POST', 'lock/self/[,)' ],
    'DELETE LOCK SELF [,)' => [ 'DELETE', 'lock/self/[,)' ],
    'GET LOCK SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'GET', 'lock/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],
    'PUT LOCK SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'PUT', 'lock/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],
    'POST LOCK SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'POST', 'lock/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],
    'DELETE LOCK SELF [ "2015-02-05 10:00", "2015-02-05 16:00" )' => [ 'DELETE', 'lock/self/[ "2015-02-05 10:00", "2015-02-05 16:00" )' ],

    # Priv commands
    "GET PRIV" => [ 'GET', 'priv' ],
    "PUT PRIV" => [ 'PUT', 'priv' ],
    "POST PRIV" => [ 'POST', 'priv' ],
    "DELETE PRIV" => [ 'DELETE', 'priv' ],
    "GET PRIV EID 123" => [ 'GET', 'priv/eid/123' ],
    "PUT PRIV EID 123" => [ 'PUT', 'priv/eid/123' ],
    "POST PRIV EID 123" => [ 'POST', 'priv/eid/123' ],
    "DELETE PRIV EID 123" => [ 'DELETE', 'priv/eid/123' ],
    "GET PRIV EID 123 1999-12-31 23:59" => [ 'GET', 'priv/eid/123/1999-12-31 23:59' ],
    "PUT PRIV EID 123 1999-12-31 23:59" => [ 'PUT', 'priv/eid/123/1999-12-31 23:59' ],
    "POST PRIV EID 123 1999-12-31 23:59" => [ 'POST', 'priv/eid/123/1999-12-31 23:59' ],
    "DELETE PRIV EID 123 1999-12-31 23:59" => [ 'DELETE', 'priv/eid/123/1999-12-31 23:59' ],
    "GET PRIV HISTORY EID 123" => [ 'GET', 'priv/history/eid/123' ],
    "PUT PRIV HISTORY EID 123" => [ 'PUT', 'priv/history/eid/123' ],
    "POST PRIV HISTORY EID 123" => [ 'POST', 'priv/history/eid/123' ],
    "DELETE PRIV HISTORY EID 123" => [ 'DELETE', 'priv/history/eid/123' ],
    "GET PRIV HISTORY EID 123 [,)" => [ 'GET', 'priv/history/eid/123/[,)' ],
    "PUT PRIV HISTORY EID 123 [,)" => [ 'PUT', 'priv/history/eid/123/[,)' ],
    "POST PRIV HISTORY EID 123 [,)" => [ 'POST', 'priv/history/eid/123/[,)' ],
    "DELETE PRIV HISTORY EID 123 [,)" => [ 'DELETE', 'priv/history/eid/123/[,)' ],
    "GET PRIV HISTORY NICK foobar" => [ 'GET', 'priv/history/nick/foobar' ],
    "PUT PRIV HISTORY NICK foobar" => [ 'PUT', 'priv/history/nick/foobar' ],
    "POST PRIV HISTORY NICK foobar" => [ 'POST', 'priv/history/nick/foobar' ],
    "DELETE PRIV HISTORY NICK foobar" => [ 'DELETE', 'priv/history/nick/foobar' ],
    "GET PRIV HISTORY NICK foobar [,)" => [ 'GET', 'priv/history/nick/foobar/[,)' ],
    "PUT PRIV HISTORY NICK foobar [,)" => [ 'PUT', 'priv/history/nick/foobar/[,)' ],
    "POST PRIV HISTORY NICK foobar [,)" => [ 'POST', 'priv/history/nick/foobar/[,)' ],
    "DELETE PRIV HISTORY NICK foobar [,)" => [ 'DELETE', 'priv/history/nick/foobar/[,)' ],
    "GET PRIV HISTORY PHID 123" => [ 'GET', 'priv/history/phid/123' ],
    "PUT PRIV HISTORY PHID 123" => [ 'PUT', 'priv/history/phid/123' ],
    "POST PRIV HISTORY PHID 123" => [ 'POST', 'priv/history/phid/123' ],
    "DELETE PRIV HISTORY PHID 123" => [ 'DELETE', 'priv/history/phid/123' ],
    "GET PRIV HISTORY SELF" => [ 'GET', 'priv/history/self' ],
    "PUT PRIV HISTORY SELF" => [ 'PUT', 'priv/history/self' ],
    "POST PRIV HISTORY SELF" => [ 'POST', 'priv/history/self' ],
    "DELETE PRIV HISTORY SELF" => [ 'DELETE', 'priv/history/self' ],
    "GET PRIV HISTORY SELF [,)" => [ 'GET', 'priv/history/self/[,)' ],
    "PUT PRIV HISTORY SELF [,)" => [ 'PUT', 'priv/history/self/[,)' ],
    "POST PRIV HISTORY SELF [,)" => [ 'POST', 'priv/history/self/[,)' ],
    "DELETE PRIV HISTORY SELF [,)" => [ 'DELETE', 'priv/history/self/[,)' ],
    "GET PRIV NICK foobar" => [ 'GET', 'priv/nick/foobar' ],
    "PUT PRIV NICK foobar" => [ 'PUT', 'priv/nick/foobar' ],
    "POST PRIV NICK foobar" => [ 'POST', 'priv/nick/foobar' ],
    "DELETE PRIV NICK foobar" => [ 'DELETE', 'priv/nick/foobar' ],
    "GET PRIV NICK foobar 2015-02-03 33:99" => [ 'GET', 'priv/nick/foobar/2015-02-03 33:99' ],
    "PUT PRIV NICK foobar 2015-02-03 33:99" => [ 'PUT', 'priv/nick/foobar/2015-02-03 33:99' ],
    "POST PRIV NICK foobar 2015-02-03 33:99" => [ 'POST', 'priv/nick/foobar/2015-02-03 33:99' ],
    "DELETE PRIV NICK foobar 2015-02-03 33:99" => [ 'DELETE', 'priv/nick/foobar/2015-02-03 33:99' ],
    "GET PRIV SELF" => [ 'GET', 'priv/self' ],
    "PUT PRIV SELF" => [ 'PUT', 'priv/self' ],
    "POST PRIV SELF" => [ 'POST', 'priv/self' ],
    "DELETE PRIV SELF" => [ 'DELETE', 'priv/self' ],
    "GET PRIV SELF 2015-02-03 33:99" => [ 'GET', 'priv/self/2015-02-03 33:99' ],
    "PUT PRIV SELF 2015-02-03 33:99" => [ 'PUT', 'priv/self/2015-02-03 33:99' ],
    "POST PRIV SELF 2015-02-03 33:99" => [ 'POST', 'priv/self/2015-02-03 33:99' ],
    "DELETE PRIV SELF 2015-02-03 33:99" => [ 'DELETE', 'priv/self/2015-02-03 33:99' ],

    # Schedule commands
    "GET SCHEDULE" => [ 'GET', 'schedule' ],
    "PUT SCHEDULE" => [ 'PUT', 'schedule' ],
    "POST SCHEDULE" => [ 'POST', 'schedule' ],
    "DELETE SCHEDULE" => [ 'DELETE', 'schedule' ],
    "GET SCHEDULE ALL" => [ 'GET', 'schedule/all' ],
    "PUT SCHEDULE ALL" => [ 'PUT', 'schedule/all' ],
    "POST SCHEDULE ALL" => [ 'POST', 'schedule/all' ],
    "DELETE SCHEDULE ALL" => [ 'DELETE', 'schedule/all' ],
    "GET SCHEDULE ALL DISABLED" => [ 'GET', 'schedule/all/disabled' ],
    "PUT SCHEDULE ALL DISABLED" => [ 'PUT', 'schedule/all/disabled' ],
    "POST SCHEDULE ALL DISABLED" => [ 'POST', 'schedule/all/disabled' ],
    "DELETE SCHEDULE ALL DISABLED" => [ 'DELETE', 'schedule/all/disabled' ],
    "GET SCHEDULE EID 123" => [ 'GET', 'schedule/eid/123' ],
    "PUT SCHEDULE EID 123" => [ 'PUT', 'schedule/eid/123' ],
    "POST SCHEDULE EID 123" => [ 'POST', 'schedule/eid/123' ],
    "DELETE SCHEDULE EID 123" => [ 'DELETE', 'schedule/eid/123' ],
    "GET SCHEDULE EID 123 1999-12-31 23:59" => [ 'GET', 'schedule/eid/123/1999-12-31 23:59' ],
    "PUT SCHEDULE EID 123 1999-12-31 23:59" => [ 'PUT', 'schedule/eid/123/1999-12-31 23:59' ],
    "POST SCHEDULE EID 123 1999-12-31 23:59" => [ 'POST', 'schedule/eid/123/1999-12-31 23:59' ],
    "DELETE SCHEDULE EID 123 1999-12-31 23:59" => [ 'DELETE', 'schedule/eid/123/1999-12-31 23:59' ],
    "GET SCHEDULE HISTORY EID 123" => [ 'GET', 'schedule/history/eid/123' ],
    "PUT SCHEDULE HISTORY EID 123" => [ 'PUT', 'schedule/history/eid/123' ],
    "POST SCHEDULE HISTORY EID 123" => [ 'POST', 'schedule/history/eid/123' ],
    "DELETE SCHEDULE HISTORY EID 123" => [ 'DELETE', 'schedule/history/eid/123' ],
    "GET SCHEDULE HISTORY EID 123 [,)" => [ 'GET', 'schedule/history/eid/123/[,)' ],
    "PUT SCHEDULE HISTORY EID 123 [,)" => [ 'PUT', 'schedule/history/eid/123/[,)' ],
    "POST SCHEDULE HISTORY EID 123 [,)" => [ 'POST', 'schedule/history/eid/123/[,)' ],
    "DELETE SCHEDULE HISTORY EID 123 [,)" => [ 'DELETE', 'schedule/history/eid/123/[,)' ],
    "GET SCHEDULE HISTORY NICK foobar" => [ 'GET', 'schedule/history/nick/foobar' ],
    "PUT SCHEDULE HISTORY NICK foobar" => [ 'PUT', 'schedule/history/nick/foobar' ],
    "POST SCHEDULE HISTORY NICK foobar" => [ 'POST', 'schedule/history/nick/foobar' ],
    "DELETE SCHEDULE HISTORY NICK foobar" => [ 'DELETE', 'schedule/history/nick/foobar' ],
    "GET SCHEDULE HISTORY NICK foobar [,)" => [ 'GET', 'schedule/history/nick/foobar/[,)' ],
    "PUT SCHEDULE HISTORY NICK foobar [,)" => [ 'PUT', 'schedule/history/nick/foobar/[,)' ],
    "POST SCHEDULE HISTORY NICK foobar [,)" => [ 'POST', 'schedule/history/nick/foobar/[,)' ],
    "DELETE SCHEDULE HISTORY NICK foobar [,)" => [ 'DELETE', 'schedule/history/nick/foobar/[,)' ],
    "GET SCHEDULE HISTORY SELF" => [ 'GET', 'schedule/history/self' ],
    "PUT SCHEDULE HISTORY SELF" => [ 'PUT', 'schedule/history/self' ],
    "POST SCHEDULE HISTORY SELF" => [ 'POST', 'schedule/history/self' ],
    "DELETE SCHEDULE HISTORY SELF" => [ 'DELETE', 'schedule/history/self' ],
    "GET SCHEDULE HISTORY SELF [,)" => [ 'GET', 'schedule/history/self/[,)' ],
    "PUT SCHEDULE HISTORY SELF [,)" => [ 'PUT', 'schedule/history/self/[,)' ],
    "POST SCHEDULE HISTORY SELF [,)" => [ 'POST', 'schedule/history/self/[,)' ],
    "DELETE SCHEDULE HISTORY SELF [,)" => [ 'DELETE', 'schedule/history/self/[,)' ],
    "GET SCHEDULE HISTORY SHID 123" => [ 'GET', 'schedule/history/shid/123' ],
    "PUT SCHEDULE HISTORY SHID 123" => [ 'PUT', 'schedule/history/shid/123' ],
    "POST SCHEDULE HISTORY SHID 123" => [ 'POST', 'schedule/history/shid/123' ],
    "DELETE SCHEDULE HISTORY SHID 123" => [ 'DELETE', 'schedule/history/shid/123' ],
    "GET SCHEDULE NICK foobar" => [ 'GET', 'schedule/nick/foobar' ],
    "PUT SCHEDULE NICK foobar" => [ 'PUT', 'schedule/nick/foobar' ],
    "POST SCHEDULE NICK foobar" => [ 'POST', 'schedule/nick/foobar' ],
    "DELETE SCHEDULE NICK foobar" => [ 'DELETE', 'schedule/nick/foobar' ],
    "GET SCHEDULE NICK foobar 2015-02-03 33:99" => [ 'GET', 'schedule/nick/foobar/2015-02-03 33:99' ],
    "PUT SCHEDULE NICK foobar 2015-02-03 33:99" => [ 'PUT', 'schedule/nick/foobar/2015-02-03 33:99' ],
    "POST SCHEDULE NICK foobar 2015-02-03 33:99" => [ 'POST', 'schedule/nick/foobar/2015-02-03 33:99' ],
    "DELETE SCHEDULE NICK foobar 2015-02-03 33:99" => [ 'DELETE', 'schedule/nick/foobar/2015-02-03 33:99' ],
    "GET SCHEDULE SCODE bubba" => [ 'GET', 'schedule/scode/bubba' ],
    "PUT SCHEDULE SCODE bubba" => [ 'PUT', 'schedule/scode/bubba' ],
    "POST SCHEDULE SCODE bubba" => [ 'POST', 'schedule/scode/bubba' ],
    "DELETE SCHEDULE SCODE bubba" => [ 'DELETE', 'schedule/scode/bubba' ],
    "GET SCHEDULE SELF" => [ 'GET', 'schedule/self' ],
    "PUT SCHEDULE SELF" => [ 'PUT', 'schedule/self' ],
    "POST SCHEDULE SELF" => [ 'POST', 'schedule/self' ],
    "DELETE SCHEDULE SELF" => [ 'DELETE', 'schedule/self' ],
    "GET SCHEDULE SELF 2015-02-03 33:99" => [ 'GET', 'schedule/self/2015-02-03 33:99' ],
    "PUT SCHEDULE SELF 2015-02-03 33:99" => [ 'PUT', 'schedule/self/2015-02-03 33:99' ],
    "POST SCHEDULE SELF 2015-02-03 33:99" => [ 'POST', 'schedule/self/2015-02-03 33:99' ],
    "DELETE SCHEDULE SELF 2015-02-03 33:99" => [ 'DELETE', 'schedule/self/2015-02-03 33:99' ],
    "GET SCHEDULE SID 93" => [ 'GET', 'schedule/sid/93' ],
    "PUT SCHEDULE SID 93" => [ 'PUT', 'schedule/sid/93' ],
    "POST SCHEDULE SID 93" => [ 'POST', 'schedule/sid/93' ],
    "DELETE SCHEDULE SID 93" => [ 'DELETE', 'schedule/sid/93' ],
);

# run look_up_command for each key in %map and execute the resulting coderef
# its return value should == map value
# (this tests basic command lookup functionality)
my %map1 = map { $_ => [ $map{ $_ }->[0], $map{ $_ }->[1], '' ] } keys( %map );

foreach my $cmd ( sort keys %map1 ) {



( run in 0.455 second using v1.01-cache-2.11-cpan-4e96b696675 )