diff --git a/cms/cms.ecf b/cms/cms.ecf index 6aa2623..dc20d24 100644 --- a/cms/cms.ecf +++ b/cms/cms.ecf @@ -10,6 +10,7 @@ + diff --git a/cms/src/configuration/cms_default_setup.e b/cms/src/configuration/cms_default_setup.e index 74f0754..dac8deb 100644 --- a/cms/src/configuration/cms_default_setup.e +++ b/cms/src/configuration/cms_default_setup.e @@ -85,6 +85,10 @@ feature {NONE} -- Initialization create {NODE_MODULE} m.make (Current) m.enable modules.extend (m) + + create {BASIC_AUTH_MODULE} m.make (Current) + m.enable + modules.extend (m) end build_api_service diff --git a/cms/src/modules/basic_auth/basic_auth_module.e b/cms/src/modules/basic_auth/basic_auth_module.e new file mode 100644 index 0000000..f669a6d --- /dev/null +++ b/cms/src/modules/basic_auth/basic_auth_module.e @@ -0,0 +1,79 @@ +note + description: "Summary description for {BASIC_AUTH_MODULE}." + date: "$Date$" + revision: "$Revision$" + +class + BASIC_AUTH_MODULE + +inherit + + CMS_MODULE + +create + make + +feature {NONE} -- Initialization + + make (a_config: CMS_SETUP) + do + name := "basic auth" + version := "1.0" + description := "Service to manage basic authentication" + package := "core" + config := a_config + setup_router + setup_filter + enable + end + +feature -- Access + + router: WSF_ROUTER + -- Node router. + + config: CMS_SETUP + -- Node configuration. + +feature -- Implementation + + setup_router + -- Setup `router'. + do + create router.make (2) + configure_api_login + configure_api_logoff + end + + setup_filter + -- Setup `filter'. + do + add_filter (create {CORS_FILTER}) + add_filter (create {BASIC_AUTH_FILTER}.make (config)) + end + +feature -- Configure Node Resources Routes + + configure_api_login + local + l_bal_handler: BASIC_AUTH_LOGIN_HANDLER + l_methods: WSF_REQUEST_METHODS + do + create l_bal_handler.make (config) + create l_methods + l_methods.enable_get + router.handle_with_request_methods ("/basic_auth/login", l_bal_handler, l_methods) + end + + configure_api_logoff + local + l_bal_handler: BASIC_AUTH_LOGOFF_HANDLER + l_methods: WSF_REQUEST_METHODS + do + create l_bal_handler.make (config) + create l_methods + l_methods.enable_get + router.handle_with_request_methods ("/basic_auth/logoff", l_bal_handler, l_methods) + end + +end diff --git a/cms/src/modules/basic_auth/filter/basic_auth_filter.e b/cms/src/modules/basic_auth/filter/basic_auth_filter.e new file mode 100644 index 0000000..1b4502b --- /dev/null +++ b/cms/src/modules/basic_auth/filter/basic_auth_filter.e @@ -0,0 +1,51 @@ +note + description: "Summary description for {BASIC_AUTH_FILTER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + BASIC_AUTH_FILTER + +inherit + + WSF_URI_TEMPLATE_HANDLER + CMS_HANDLER + WSF_FILTER + +create + make + +feature -- Basic operations + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the filter + local + l_auth: HTTP_AUTHORIZATION + do + log.write_debug (generator + ".execute " ) + create l_auth.make (req.http_authorization) + if attached req.raw_header_data as l_raw_data then + log.write_debug (generator + ".execute " + l_raw_data ) + end + -- A valid user + if (attached l_auth.type as l_auth_type and then l_auth_type.is_case_insensitive_equal_general ("basic")) and then + attached l_auth.login as l_auth_login and then attached l_auth.password as l_auth_password then + if api_service.login_valid (l_auth_login, l_auth_password) then + if attached api_service.user_by_name (l_auth_login) as l_user then + req.set_execution_variable ("user", l_user) + execute_next (req, res) + else + -- Internal server error + end + else + log.write_error (generator + ".execute login_valid failed for: " + l_auth_login ) + execute_next (req, res) + end + else + log.write_error (generator + ".execute Not valid") + execute_next (req, res) + end + end + +end diff --git a/cms/src/modules/basic_auth/filter/cors_filter.e b/cms/src/modules/basic_auth/filter/cors_filter.e new file mode 100644 index 0000000..bea5958 --- /dev/null +++ b/cms/src/modules/basic_auth/filter/cors_filter.e @@ -0,0 +1,28 @@ +note + description: "CORS filter" + date: "$Date: 2014-08-08 16:02:11 -0300 (vi., 08 ago. 2014) $" + revision: "$Revision: 95593 $" + +class + CORS_FILTER + +inherit + + WSF_FILTER + +feature -- Basic operations + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the filter. + local + l_header: HTTP_HEADER + do + create l_header.make +-- l_header.add_header_key_value ("Access-Control-Allow-Origin", "localhost") + l_header.add_header_key_value ("Access-Control-Allow-Headers", "*") + l_header.add_header_key_value ("Access-Control-Allow-Methods", "*") + l_header.add_header_key_value ("Access-Control-Allow-Credentials", "true") + res.put_header_lines (l_header) + execute_next (req, res) + end +end diff --git a/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e b/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e new file mode 100644 index 0000000..8f27b2f --- /dev/null +++ b/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e @@ -0,0 +1,62 @@ +note + description: "Summary description for {BASIC_AUTH_LOGIN_HANDLER}." + date: "$Date$" + revision: "$Revision$" + +class + BASIC_AUTH_LOGIN_HANDLER + +inherit + CMS_HANDLER + + WSF_URI_HANDLER + rename + execute as uri_execute, + new_mapping as new_uri_mapping + end + + WSF_FILTER + + + WSF_RESOURCE_HANDLER_HELPER + redefine + do_get + end + + REFACTORING_HELPER + +create + make + +feature -- execute + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute request handler. + do + execute_methods (req, res) + execute_next (req, res) + end + + uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute request handler. + do + execute_methods (req, res) + end + +feature -- HTTP Methods + + do_get (req: WSF_REQUEST; res: WSF_RESPONSE) + -- + local + l_page: CMS_RESPONSE + do + log.write_information(generator + ".do_get Processing basic auth login") + if attached {STRING_32} current_user_name (req) as l_user then + (create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url("")) + else + (create {CMS_GENERIC_RESPONSE}).new_response_authenticate (req, res) + end + end + + +end diff --git a/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e b/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e new file mode 100644 index 0000000..b274ab4 --- /dev/null +++ b/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e @@ -0,0 +1,59 @@ +note + description: "Summary description for {BASIC_AUTH_LOGOFF_HANDLER}." + date: "$Date$" + revision: "$Revision$" + +class + BASIC_AUTH_LOGOFF_HANDLER + +inherit + CMS_HANDLER + + WSF_URI_HANDLER + rename + execute as uri_execute, + new_mapping as new_uri_mapping + end + + WSF_RESOURCE_HANDLER_HELPER + redefine + do_get + end + + REFACTORING_HELPER + +create + make + +feature -- execute + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute request handler. + do + execute_methods (req, res) + end + + uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute request handler. + do + execute_methods (req, res) + end + +feature -- HTTP Methods + + do_get (req: WSF_REQUEST; res: WSF_RESPONSE) + -- + local + l_page: CMS_RESPONSE + do + log.write_information(generator + ".do_get Processing basic auth logoff") + if attached req.query_parameter ("prompt") as l_prompt then + (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) + else + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/basic_auth/logoff") + l_page.set_status_code ({HTTP_STATUS_CODE}.unauthorized) + l_page.execute + end + end + +end diff --git a/cms/src/modules/cms_module.e b/cms/src/modules/cms_module.e index 4a40053..3979fff 100644 --- a/cms/src/modules/cms_module.e +++ b/cms/src/modules/cms_module.e @@ -25,6 +25,26 @@ feature -- Router deferred end +feature -- Filter + + filters: detachable LIST[WSF_FILTER] + -- Possibly list of Filter's module. + +feature -- Element Change: Filter + + add_filter (a_filter: WSF_FILTER) + -- Add a filter `a_filter' to the list of module filters `filters'. + local + l_filters: like filters + do + l_filters := filters + if l_filters = Void then + create {ARRAYED_LIST[WSF_FILTER]}l_filters.make (1) + filters := l_filters + end + l_filters.force (a_filter) + end + feature -- Settings enable diff --git a/cms/src/service/cms_service.e b/cms/src/service/cms_service.e index 85fb7a1..f786a83 100644 --- a/cms/src/service/cms_service.e +++ b/cms/src/service/cms_service.e @@ -11,6 +11,8 @@ class inherit WSF_ROUTED_SKELETON_SERVICE + rename + execute as execute_service undefine requires_proxy redefine @@ -44,15 +46,15 @@ feature {NONE} -- Initialization setup := a_setup configuration := a_setup.configuration modules := a_setup.modules + create {ARRAYED_LIST[WSF_FILTER]} filters.make (0) initialize_users initialize_auth_engine initialize_mailer initialize_router initialize_modules + initialize_filter end - - initialize_users do end @@ -78,6 +80,9 @@ feature {NONE} -- Initialization if m.item.is_enabled then router.import (m.item.router) end + if attached m.item.filters as l_m_filters then + filters.append (l_m_filters) + end end configure_api_file_handler end @@ -98,6 +103,7 @@ feature {NONE} -- Initialization create l_methods l_methods.enable_get router.handle_with_request_methods ("/", l_root_handler, l_methods) + router.handle_with_request_methods ("", l_root_handler, l_methods) end configure_api_file_handler @@ -128,10 +134,57 @@ feature -- Access -- List of possible modules. -- | Maybe we can compute it (using `setup') instead of using memory. -feature -- Logging + filters: LIST[WSF_FILTER] + -- List of possible filters. -feature -- Notification +feature -- Execute Filter + execute_filter (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the filter. + do + + res.put_header_line ("Date: " + (create {HTTP_DATE}.make_now_utc).string) + execute_service (req, res) + end + +feature -- Filters + + create_filter + -- Create `filter'. + local + f, l_filter: detachable WSF_FILTER + fh: WSF_CUSTOM_HEADER_FILTER + do + l_filter := Void + -- Maintenance + create {WSF_MAINTENANCE_FILTER} f + f.set_next (l_filter) + l_filter := f + + if attached filters as l_filters then + across l_filters as c loop + c.item.set_next (l_filter) + l_filter := c.item + end + end + + filter := l_filter + end + + setup_filter + -- Setup `filter'. + local + f: WSF_FILTER + do + from + f := filter + until + not attached f.next as l_next + loop + f := l_next + end + f.set_next (Current) + end feature -- Execution diff --git a/cms/src/service/response/cms_generic_response.e b/cms/src/service/response/cms_generic_response.e index 872e852..380a391 100644 --- a/cms/src/service/response/cms_generic_response.e +++ b/cms/src/service/response/cms_generic_response.e @@ -29,7 +29,7 @@ feature -- Responses create h.make h.put_content_type_text_html h.put_current_date - h.put_header_key_value ({HTTP_HEADER_NAMES}.header_www_authenticate, "Basic realm=%"CMS-User%"") + h.put_header_key_value ({HTTP_HEADER_NAMES}.header_www_authenticate, "Basic realm=%"CMSRoc-User%"") res.set_status_code ({HTTP_STATUS_CODE}.unauthorized) res.put_header_text (h.string) end diff --git a/cms/src/service/response/home_cms_response.e b/cms/src/service/response/home_cms_response.e index b38c0e4..cf51ad9 100644 --- a/cms/src/service/response/home_cms_response.e +++ b/cms/src/service/response/home_cms_response.e @@ -20,6 +20,7 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do + Precursor (page) page.register_variable (setup.api_service.recent_nodes (0, 5), "nodes") end diff --git a/examples/api/src/roc_server.e b/examples/api/src/roc_server.e index 0a4c090..20d9d7d 100644 --- a/examples/api/src/roc_server.e +++ b/examples/api/src/roc_server.e @@ -174,6 +174,12 @@ feature -- Filters f.set_next (l_filter) l_filter := f + -- Authentication + create {AUTHENTICATION_FILTER} f.make (roc_config) + f.set_next (l_filter) + l_filter := f + + -- Logger Filter create {LOGGER_FILTER} f.make (roc_config) f.set_next (l_filter) @@ -184,10 +190,6 @@ feature -- Filters f.set_next (l_filter) l_filter := f - -- Authentication - create {AUTHENTICATION_FILTER} f.make (roc_config) - f.set_next (l_filter) - l_filter := f filter := l_filter end diff --git a/examples/api/src/service/handler/roc_logoff_handler.e b/examples/api/src/service/handler/roc_logoff_handler.e index dcc0071..5e85400 100644 --- a/examples/api/src/service/handler/roc_logoff_handler.e +++ b/examples/api/src/service/handler/roc_logoff_handler.e @@ -52,6 +52,7 @@ feature -- HTTP Methods if attached req.query_parameter ("prompt") as l_prompt then (create {ROC_RESPONSE}.make(req,"")).new_response_unauthorized (req, res) else + req.unset_execution_variable ("user") (create {ROC_RESPONSE}.make(req,"master2/logoff.tpl")).new_response_denied (req, res) end end diff --git a/examples/roc_api/site/www/themes/api/master2/logoff.tpl b/examples/roc_api/site/www/themes/api/master2/basic_auth/logoff.tpl similarity index 100% rename from examples/roc_api/site/www/themes/api/master2/logoff.tpl rename to examples/roc_api/site/www/themes/api/master2/basic_auth/logoff.tpl diff --git a/examples/roc_api/site/www/themes/api/master2/site_navigation.tpl b/examples/roc_api/site/www/themes/api/master2/site_navigation.tpl index a75760c..d37ce73 100644 --- a/examples/roc_api/site/www/themes/api/master2/site_navigation.tpl +++ b/examples/roc_api/site/www/themes/api/master2/site_navigation.tpl @@ -12,10 +12,10 @@ {if isset="$user"}
  • {$user/}
  • New Node
  • -
  • Logoff
  • +
  • Logoff
  • {/if} {unless isset="$user"} -
  • Login
  • +
  • Login
  • Register
  • {/unless}