")
+ if a_err /= Void then
+ Result.append ("
")
+ Result.append (a_err)
+ Result.append ("
")
+ end
+ Result.append ("
")
+ end
+
+end
diff --git a/examples/demo/demo.ecf b/examples/demo/demo.ecf
index 7df2c04..8163de4 100644
--- a/examples/demo/demo.ecf
+++ b/examples/demo/demo.ecf
@@ -29,7 +29,7 @@
diff --git a/examples/demo/site/themes/bootstrap/search.tpl b/examples/demo/site/themes/bootstrap/search.tpl
new file mode 100644
index 0000000..1cedbb4
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/search.tpl
@@ -0,0 +1,6 @@
+
diff --git a/examples/demo/site/themes/bootstrap/theme.info b/examples/demo/site/themes/bootstrap/theme.info
index 6c96570..9ba80a7 100644
--- a/examples/demo/site/themes/bootstrap/theme.info
+++ b/examples/demo/site/themes/bootstrap/theme.info
@@ -4,6 +4,7 @@ author=jvelilla
version=0.1
regions[page_top] = Top
regions[header] = Header
+regions[search] = Search
regions[content] = Content
regions[highlighted] = Highlighted
regions[help] = Help
diff --git a/examples/demo/src/demo_cms_execution.e b/examples/demo/src/demo_cms_execution.e
index 4dc81a2..71613e4 100644
--- a/examples/demo/src/demo_cms_execution.e
+++ b/examples/demo/src/demo_cms_execution.e
@@ -86,11 +86,14 @@ feature -- CMS modules
-- Miscellanious
a_setup.register_module (create {CMS_MESSAGING_MODULE}.make)
- a_setup.register_module (create {GOOGLE_CUSTOM_SEARCH_MODULE}.make)
+ a_setup.register_module (create {GOOGLE_CUSTOM_SEARCH_MODULE_20}.make)
a_setup.register_module (create {CMS_CUSTOM_BLOCK_MODULE}.make)
a_setup.register_module (create {CMS_DEBUG_MODULE}.make)
a_setup.register_module (create {CMS_DEMO_MODULE}.make)
+ -- Dev
+ a_setup.register_module (create {MASQUERADE_AUTH_MODULE}.make)
+
end
end
diff --git a/modules/google_search_20/Readme.md b/modules/google_search_20/Readme.md
new file mode 100644
index 0000000..71df20c
--- /dev/null
+++ b/modules/google_search_20/Readme.md
@@ -0,0 +1,13 @@
+Google Custom Search Module 2.0.
+
+# Based on Google Custom Search Engine (CSE)
+- https://developers.google.com/custom-search/docs/element
+- Search form provides a parameter `q` for the search query.
+- Results are displayed in associated page /gcse2 (using
)
+
+# Settings
+- edit the `site/modules/google_search_20/config/google_search_20.json` file, and set the value `gcse.search_engine_id`.
+
+# How to get a Custom Search engine ID?
+- See https://support.google.com/customsearch/answer/2649143?hl=en
+- https://cse.google.com/all
diff --git a/modules/google_search_20/google_search_20-safe.ecf b/modules/google_search_20/google_search_20-safe.ecf
new file mode 100644
index 0000000..5e0ece5
--- /dev/null
+++ b/modules/google_search_20/google_search_20-safe.ecf
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/google_search_20/google_search_20.ecf b/modules/google_search_20/google_search_20.ecf
new file mode 100644
index 0000000..4c86d8f
--- /dev/null
+++ b/modules/google_search_20/google_search_20.ecf
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/google_search_20/site/config/google_search_20.json-dist b/modules/google_search_20/site/config/google_search_20.json-dist
new file mode 100644
index 0000000..ea94f8a
--- /dev/null
+++ b/modules/google_search_20/site/config/google_search_20.json-dist
@@ -0,0 +1,5 @@
+{
+ "gcse": {
+ "search_engine_id":""
+ }
+}
diff --git a/modules/google_search_20/site/templates/block_gcse_search_form.tpl b/modules/google_search_20/site/templates/block_gcse_search_form.tpl
new file mode 100644
index 0000000..4542f09
--- /dev/null
+++ b/modules/google_search_20/site/templates/block_gcse_search_form.tpl
@@ -0,0 +1,6 @@
+
diff --git a/modules/google_search_20/site/templates/block_gcse_search_results.tpl b/modules/google_search_20/site/templates/block_gcse_search_results.tpl
new file mode 100644
index 0000000..056ad79
--- /dev/null
+++ b/modules/google_search_20/site/templates/block_gcse_search_results.tpl
@@ -0,0 +1,7 @@
+
+
+ Results for {$cms_search_query/}
+
+
+
+
diff --git a/modules/google_search_20/src/google_custom_search_module_20.e b/modules/google_search_20/src/google_custom_search_module_20.e
new file mode 100644
index 0000000..2c85e12
--- /dev/null
+++ b/modules/google_search_20/src/google_custom_search_module_20.e
@@ -0,0 +1,156 @@
+note
+ description: "[
+ Module providing Google Custom Search functionality.
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ GOOGLE_CUSTOM_SEARCH_MODULE_20
+
+inherit
+ CMS_MODULE
+ redefine
+ setup_hooks
+ end
+
+ CMS_HOOK_AUTO_REGISTER
+
+ REFACTORING_HELPER
+
+ CMS_HOOK_BLOCK
+
+ CMS_HOOK_BLOCK_HELPER
+
+ SHARED_EXECUTION_ENVIRONMENT
+ export
+ {NONE} all
+ end
+
+ REFACTORING_HELPER
+
+ SHARED_LOGGER
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ -- Create current module
+ do
+ version := "2.0"
+ description := "Google custome search module 2.0"
+ package := "search"
+ end
+
+feature -- Access
+
+ name: STRING = "google_search_20"
+ --
+
+feature -- Router
+
+ setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
+ -- Router configuration.
+ local
+ m: WSF_URI_MAPPING
+ do
+ create m.make_trailing_slash_ignored ("/gcse20", create {WSF_URI_AGENT_HANDLER}.make (agent handle_search (a_api, ?, ?)))
+ a_router.map (m, a_router.methods_head_get)
+ end
+
+feature -- GCSE Keys
+
+ gcse_cx_key (api: CMS_API): detachable READABLE_STRING_8
+ -- Get google custom search engine id.
+ local
+ utf: UTF_CONVERTER
+ do
+ if attached api.module_configuration (Current, Void) as cfg then
+ if
+ attached cfg.text_item ("gcse.search_engine_id") as l_gcse_cx_key and then
+ not l_gcse_cx_key.is_empty
+ then
+ Result := utf.utf_32_string_to_utf_8_string_8 (l_gcse_cx_key)
+ end
+ end
+ end
+
+feature -- Handler
+
+ handle_search (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ r: CMS_RESPONSE
+ l_script: STRING
+ b: CMS_CONTENT_BLOCK
+ do
+ write_debug_log (generator + ".handle_search")
+ create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
+ if
+ attached {WSF_STRING} req.query_parameter ("q") as l_query and then
+ not l_query.value.is_empty
+ then
+ if
+ attached gcse_cx_key (api) as l_cx
+ then
+ r.set_value (l_query.value, "cms_search_query")
+ if
+ attached smarty_template_block (Current, "gcse_search_results", api) as l_tpl_block
+ then
+ r.add_block (l_tpl_block, "content")
+
+ if attached gcse_cx_key (api) as l_ctx then
+ create l_script.make_from_string (gcse_20_script)
+ l_script.replace_substring_all ("#CX_VALUE", l_ctx)
+ create b.make_raw ("gcse2_js", Void, "", Void)
+ r.add_block (b, "footer")
+ end
+ end
+ end
+ else
+ r.add_message ("No query submitted", Void)
+ end
+ r.execute
+ end
+
+feature -- Hooks configuration
+
+ setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
+ -- Module hooks configuration.
+ do
+ auto_subscribe_to_hooks (a_hooks)
+ end
+
+ block_list: ITERABLE [like {CMS_BLOCK}.name]
+ do
+ Result := <<"gcse_search_form">>
+ end
+
+ get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
+ do
+ if a_block_id.is_case_insensitive_equal_general ("gcse_search_form") then
+ if a_response.request.is_get_request_method then
+ if attached smarty_template_block (Current, a_block_id, a_response.api) as l_tpl_block then
+ a_response.add_block (l_tpl_block, "search")
+ else
+ debug ("cms")
+ a_response.add_warning_message ("Error with block [" + a_block_id + "]")
+ end
+ end
+ end
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ gcse_20_script: STRING = "[
+ (function() {
+ var cx = '#CX_VALUE';
+ var gcse = document.createElement('script'); gcse.type = 'text/javascript'; gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//www.google.com/cse/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+ ]"
+end
diff --git a/modules/session_auth/cms_session_api.e b/modules/session_auth/cms_session_api.e
index ac02417..6def2a0 100644
--- a/modules/session_auth/cms_session_api.e
+++ b/modules/session_auth/cms_session_api.e
@@ -57,6 +57,18 @@ feature -- Settings
session_max_age: INTEGER
-- Value of the Max-Age, before the cookie expires.
+feature -- Status report
+
+ is_authenticating (a_response: CMS_RESPONSE): BOOLEAN
+ do
+ if
+ a_response.is_authenticated and then
+ attached a_response.request.cookie (session_token)
+ then
+ Result := True
+ end
+ end
+
feature -- Access
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER
@@ -71,6 +83,47 @@ feature -- Access
Result := session_auth_storage.has_user_token (a_user)
end
+feature -- Basic operation
+
+ process_user_login (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ l_token: STRING
+ l_cookie: WSF_COOKIE
+ do
+ l_token := new_session_token
+ if has_user_token (a_user) then
+ update_user_session_auth (l_token, a_user)
+ else
+ new_user_session_auth (l_token, a_user)
+ end
+ create l_cookie.make (session_token, l_token)
+ l_cookie.set_max_age (session_max_age)
+ l_cookie.set_path ("/")
+ res.add_cookie (l_cookie)
+ cms_api.set_user (a_user)
+ cms_api.record_user_login (a_user)
+ end
+
+ process_user_logout (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ l_cookie: WSF_COOKIE
+ do
+ if
+ attached session_token as tok and then
+ attached {WSF_STRING} req.cookie (tok) as l_cookie_token
+ then
+ -- Logout Session
+ create l_cookie.make (tok, "") -- l_cookie_token.value) -- FIXME: unicode issue?
+ l_cookie.set_path ("/")
+ l_cookie.unset_max_age
+ l_cookie.set_expiration_date (create {DATE_TIME}.make_from_epoch (0))
+ res.add_cookie (l_cookie)
+ else
+ -- it seems the user was not login, as there is no associated cookie!
+ end
+ cms_api.unset_user
+ end
+
feature -- Change User session
new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;)
@@ -86,4 +139,26 @@ feature -- Change User session
session_auth_storage.update_user_session_auth (a_token, a_user)
end
+feature -- Token
+
+ new_session_token: STRING
+ -- Generate token to use in a Session.
+ local
+ l_token: STRING
+ l_security: CMS_TOKEN_GENERATOR
+ l_encode: URL_ENCODER
+ do
+ create l_security
+ l_token := l_security.token
+ create l_encode
+ from until l_token.same_string (l_encode.encoded_string (l_token)) loop
+ -- Loop ensure that we have a security token that does not contain characters that need encoding.
+ -- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token
+ -- but the user will need to use an unencoded token if activation has to be done manually.
+ l_token := l_security.token
+ end
+ Result := l_token
+ end
+
+
end
diff --git a/modules/session_auth/cms_session_auth_module.e b/modules/session_auth/cms_session_auth_module.e
index b9f4e5b..9abc865 100644
--- a/modules/session_auth/cms_session_auth_module.e
+++ b/modules/session_auth/cms_session_auth_module.e
@@ -100,11 +100,9 @@ feature -- Access: auth strategy
--
do
if
- a_response.is_authenticated and then
- attached session_api as l_session_api and then
- attached a_response.request.cookie (l_session_api.session_token)
+ attached session_api as l_session_api
then
- Result := True
+ Result := l_session_api.is_authenticating (a_response)
end
end
@@ -116,7 +114,7 @@ feature -- Access: router
if attached session_api as l_session_api then
a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/" + logout_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_session_api, ?, ?)), a_router.methods_get_post)
- a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login_with_session (a_api,session_api, ?, ?)), a_router.methods_post)
+ a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login_with_session (a_api, l_session_api, ?, ?)), a_router.methods_post)
end
end
@@ -164,39 +162,33 @@ feature {NONE} -- Implementation: routes
handle_logout (api: CMS_API; a_session_api: CMS_SESSION_API ; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
- l_cookie: WSF_COOKIE
- tok: STRING
do
- tok := a_session_api.session_token
- if
- attached {WSF_STRING} req.cookie (tok) as l_cookie_token and then
- attached api.user as l_user
- then
- -- Logout Session
- create l_cookie.make (tok, "") -- l_cookie_token.value) -- FIXME: unicode issue?
- l_cookie.set_path ("/")
- l_cookie.unset_max_age
- l_cookie.set_expiration_date (create {DATE_TIME}.make_from_epoch (0))
- res.add_cookie (l_cookie)
- api.unset_user
-
+ if attached api.user as l_user then
+ a_session_api.process_user_logout (l_user, req, res)
+ create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
+ else
+ -- Not loggued in ... redirect to home
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.set_status_code ({HTTP_CONSTANTS}.found)
- r.set_redirection (req.absolute_script_url (""))
- r.execute
- else
- fixme (generator + ": missing else implementation in handle_logout!")
end
+ if
+ attached {WSF_STRING} req.item ("destination") as p_destination and then
+ attached p_destination.value as v and then
+ v.is_valid_as_string_8
+ then
+ r.set_redirection (v.to_string_8)
+ else
+ r.set_redirection (req.absolute_script_url (""))
+ end
+
+ r.execute
end
- handle_login_with_session (api: CMS_API; a_session_api: detachable CMS_SESSION_API; req: WSF_REQUEST; res: WSF_RESPONSE)
+ handle_login_with_session (api: CMS_API; a_session_api: CMS_SESSION_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
- l_token: STRING
- l_cookie: WSF_COOKIE
do
if
- attached a_session_api as l_session_api and then
attached {WSF_STRING} req.form_parameter ("username") as l_username and then
attached {WSF_STRING} req.form_parameter ("password") as l_password
then
@@ -204,18 +196,7 @@ feature {NONE} -- Implementation: routes
api.user_api.is_valid_credential (l_username.value, l_password.value) and then
attached api.user_api.user_by_name (l_username.value) as l_user
then
- l_token := generate_token
- if a_session_api.has_user_token (l_user) then
- l_session_api.update_user_session_auth (l_token, l_user)
- else
- l_session_api.new_user_session_auth (l_token, l_user)
- end
- create l_cookie.make (a_session_api.session_token, l_token)
- l_cookie.set_max_age (a_session_api.session_max_age)
- l_cookie.set_path ("/")
- res.add_cookie (l_cookie)
- api.set_user (l_user)
- api.record_user_login (l_user)
+ a_session_api.process_user_login (l_user, req, res)
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if
@@ -295,23 +276,4 @@ feature {NONE} -- Block views
end
end
- generate_token: STRING
- -- Generate token to use in a Session.
- local
- l_token: STRING
- l_security: CMS_TOKEN_GENERATOR
- l_encode: URL_ENCODER
- do
- create l_security
- l_token := l_security.token
- create l_encode
- from until l_token.same_string (l_encode.encoded_string (l_token)) loop
- -- Loop ensure that we have a security token that does not contain characters that need encoding.
- -- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token
- -- but the user will need to use an unencoded token if activation has to be done manually.
- l_token := l_security.token
- end
- Result := l_token
- end
-
end