diff --git a/modules/auth/cms_authentication_module.e b/modules/auth/cms_authentication_module.e index c1e3cdf..9447581 100644 --- a/modules/auth/cms_authentication_module.e +++ b/modules/auth/cms_authentication_module.e @@ -362,79 +362,78 @@ feature -- Handler l_captcha_passed: BOOLEAN l_email: READABLE_STRING_8 do - create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) - if r.has_permission ("account register") then - if req.is_post_request_method then - if - attached {WSF_STRING} req.form_parameter ("name") as l_name and then - attached {WSF_STRING} req.form_parameter ("password") as l_password and then - attached {WSF_STRING} req.form_parameter ("email") as p_email and then - attached {WSF_STRING} req.form_parameter ("personal_information") as l_personal_information - then - if p_email.value.is_valid_as_string_8 then - l_email := p_email.value.to_string_8 - l_user_api := api.user_api - if attached l_user_api.user_by_name (l_name.value) or else attached l_user_api.temp_user_by_name (l_name.value) then - -- Username already exist. - r.set_value ("User name already exists!", "error_name") - l_exist := True - end - if attached l_user_api.user_by_email (l_email) or else attached l_user_api.temp_user_by_email (l_email) then - -- Email already exists. - r.set_value ("An account is already associated with that email address!", "error_email") - l_exist := True - end - if attached recaptcha_secret_key (api) as l_recaptcha_key then - if attached {WSF_STRING} req.form_parameter ("g-recaptcha-response") as l_recaptcha_response and then is_captcha_verified (l_recaptcha_key, l_recaptcha_response.url_encoded_value) then - l_captcha_passed := True - else - --| Bad or missing captcha - l_captcha_passed := False - end - else - --| reCaptcha is not setup, so no verification + if + api.has_permission ("account register") and then + req.is_post_request_method + then + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if + attached {WSF_STRING} req.form_parameter ("name") as l_name and then + attached {WSF_STRING} req.form_parameter ("password") as l_password and then + attached {WSF_STRING} req.form_parameter ("email") as p_email and then + attached {WSF_STRING} req.form_parameter ("personal_information") as l_personal_information + then + if p_email.value.is_valid_as_string_8 then + l_email := p_email.value.to_string_8 + l_user_api := api.user_api + if attached l_user_api.user_by_name (l_name.value) or else attached l_user_api.temp_user_by_name (l_name.value) then + -- Username already exist. + r.set_value ("User name already exists!", "error_name") + l_exist := True + end + if attached l_user_api.user_by_email (l_email) or else attached l_user_api.temp_user_by_email (l_email) then + -- Email already exists. + r.set_value ("An account is already associated with that email address!", "error_email") + l_exist := True + end + if attached recaptcha_secret_key (api) as l_recaptcha_key then + if attached {WSF_STRING} req.form_parameter ("g-recaptcha-response") as l_recaptcha_response and then is_captcha_verified (l_recaptcha_key, l_recaptcha_response.url_encoded_value) then l_captcha_passed := True - end - if not l_exist then - -- New temp user - create u.make (l_name.value) - u.set_email (l_email) - u.set_password (l_password.value) - u.set_personal_information (l_personal_information.value) - l_user_api.new_temp_user (u) - - -- Create activation token - l_token := new_token - l_user_api.new_activation (l_token, u.id) - l_url_activate := req.absolute_script_url ("/account/activate/" + l_token) - l_url_reject := req.absolute_script_url ("/account/reject/" + l_token) - - -- Send Email to webmaster - create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) - write_debug_log (generator + ".handle register: send_register_email") - es.send_account_evaluation (u, l_personal_information.value, l_url_activate, l_url_reject, req.absolute_script_url ("")) - - -- Send Email to user - create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) - write_debug_log (generator + ".handle register: send_contact_email") - es.send_contact_email (l_email, u, req.absolute_script_url ("")) else - r.set_value (l_name.value, "name") - r.set_value (l_email, "email") - r.set_value (l_personal_information.value, "personal_information") - r.set_status_code ({HTTP_CONSTANTS}.bad_request) + --| Bad or missing captcha + l_captcha_passed := False end + else + --| reCaptcha is not setup, so no verification + l_captcha_passed := True + end + if not l_exist then + -- New temp user + create u.make (l_name.value) + u.set_email (l_email) + u.set_password (l_password.value) + u.set_personal_information (l_personal_information.value) + l_user_api.new_temp_user (u) + -- Create activation token + l_token := new_token + l_user_api.new_activation (l_token, u.id) + l_url_activate := req.absolute_script_url ("/account/activate/" + l_token) + l_url_reject := req.absolute_script_url ("/account/reject/" + l_token) + -- Send Email to webmaster + create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) + write_debug_log (generator + ".handle register: send_register_email") + es.send_account_evaluation (u, l_personal_information.value, l_url_activate, l_url_reject, req.absolute_script_url ("")) + + -- Send Email to user + create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) + write_debug_log (generator + ".handle register: send_contact_email") + es.send_contact_email (l_email, u, req.absolute_script_url ("")) else r.set_value (l_name.value, "name") - r.set_value (p_email.value, "email") + r.set_value (l_email, "email") r.set_value (l_personal_information.value, "personal_information") r.set_status_code ({HTTP_CONSTANTS}.bad_request) end else - api.response_api.send_bad_request ("There were issue with your application, invalid or missing values.", req, res) + r.set_value (l_name.value, "name") + r.set_value (p_email.value, "email") + r.set_value (l_personal_information.value, "personal_information") + r.set_status_code ({HTTP_CONSTANTS}.bad_request) end + r.execute + else + api.response_api.send_bad_request ("There were issue with your application, invalid or missing values.", req, res) end - r.execute else api.response_api.send_permissions_access_denied ("You can also contact the webmaster to ask for an account.", Void, req, res) end diff --git a/modules/feed_aggregator/feed_aggregation.e b/modules/feed_aggregator/feed_aggregation.e index 439a96f..ebd6964 100644 --- a/modules/feed_aggregator/feed_aggregation.e +++ b/modules/feed_aggregator/feed_aggregation.e @@ -52,14 +52,14 @@ feature -- Access feature -- Status report has_category_filter: BOOLEAN - -- Is there any category filtering? + -- Is there any global category filtering? -- i.e via `included_categories' do Result := attached included_categories as cats and then not cats.is_empty end has_category_filter_for_location (a_location: READABLE_STRING_GENERAL): BOOLEAN - -- Is there any category filtering for `a_location'? + -- Is there any specific category filtering for `a_location'? do Result := attached included_categories_per_feed as cats_per_location and then attached cats_per_location.item (a_location) as cats and then @@ -118,7 +118,7 @@ feature -- Element change end end - include_category_per_feed (a_cat: READABLE_STRING_GENERAL; a_feed_location: READABLE_STRING_8) + include_category_per_feed (a_cat: READABLE_STRING_GENERAL; a_feed_location: READABLE_STRING_GENERAL) local tb: like included_categories_per_feed lst: like included_categories @@ -163,20 +163,22 @@ feature -- Status report is_included_for_location (e: FEED_ITEM; a_location: READABLE_STRING_GENERAL): BOOLEAN -- Is `e' included in feed related to `a_location'? - -- note that if `e' has no category, it is included by default, - -- even if `included_categories_per_feed' is defined for `a_location'. + -- notes: + -- - it also check for `included_categories' condition. + -- - if `e' has no category, it is included by default, + -- even if `included_categories_per_feed' is defined for `a_location'. do - Result := True - if attached e.categories as e_cats then + Result := is_included (e) + if Result and attached e.categories as e_cats then if attached included_categories_per_feed as tb and then attached tb.item (a_location) as lst then Result := across lst as ic some - across e_cats as e_ic some - e_ic.item.same_string (ic.item) + across e_cats as e_ic some + e_ic.item.same_string (ic.item) + end end - end end end end diff --git a/modules/feed_aggregator/feed_aggregator_api.e b/modules/feed_aggregator/feed_aggregator_api.e index 1c35d43..2cfe2a4 100644 --- a/modules/feed_aggregator/feed_aggregator_api.e +++ b/modules/feed_aggregator/feed_aggregator_api.e @@ -35,6 +35,8 @@ feature -- Access l_feed_id: READABLE_STRING_32 l_title: detachable READABLE_STRING_GENERAL l_locations: detachable STRING_TABLE [READABLE_STRING_8] + loc_name: READABLE_STRING_GENERAL + loc: READABLE_STRING_8 l_table: like internal_aggregations do l_table := internal_aggregations @@ -102,6 +104,19 @@ feature -- Access agg.include_category (cats_ic.item) end end + across + l_locations as locs_ic + loop + loc_name := locs_ic.key + loc := locs_ic.item + if attached cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + {STRING_32} ".categories." + loc_name.as_string_32) as l_loc_cats then + across + l_loc_cats as cats_ic + loop + agg.include_category_per_feed (cats_ic.item, loc) + end + end + end end end end @@ -138,11 +153,42 @@ feature -- Operation aggregation_feed (agg: FEED_AGGREGATION): detachable FEED -- Feed from aggregation `agg'. + local + loc: READABLE_STRING_8 + lst: LIST [FEED_ITEM] do across agg.locations as ic loop - if attached feed (ic.item) as f then + loc := ic.item + if attached feed (loc) as f then + lst := f.items + if agg.has_category_filter_for_location (loc) then + -- Note: it also check the global filter. + from + lst.start + until + lst.after + loop + if agg.is_included_for_location (lst.item, loc) then + lst.forth + else + lst.remove + end + end + elseif agg.has_category_filter then + from + lst.start + until + lst.after + loop + if agg.is_included (lst.item) then + lst.forth + else + lst.remove + end + end + end if Result /= Void then if f /= Void then Result := Result + f @@ -152,6 +198,9 @@ feature -- Operation end end end + if Result /= Void then + Result.set_date (create {DATE_TIME}.make_now_utc) + end end new_http_client_session (a_url: READABLE_STRING_8): HTTP_CLIENT_SESSION diff --git a/modules/feed_aggregator/feed_aggregator_module.e b/modules/feed_aggregator/feed_aggregator_module.e index a843146..5ddeb55 100644 --- a/modules/feed_aggregator/feed_aggregator_module.e +++ b/modules/feed_aggregator/feed_aggregator_module.e @@ -90,16 +90,33 @@ feature -- Handle end if attached {WSF_STRING} req.path_parameter ("feed_id") as p_feed_id then if attached feed_aggregation (p_feed_id.value) as l_agg then - if attached {WSF_STRING} req.query_parameter ("view") as p_view and then p_view.same_string ("embedded") then - create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api) - if attached feed_to_html (p_feed_id.value, nb, True, r) as l_html then - r := Void + if + attached {WSF_STRING} req.query_parameter ("view") as p_view and then + p_view.same_string ("embedded") + then + if attached feed_to_html (p_feed_id.value, nb, True, create {GENERIC_VIEW_CMS_RESPONSE}.make (req, res, a_api)) as l_html then create m.make_with_body (l_html) m.header.put_content_type_text_html res.send (m) else a_api.response_api.send_not_found (Void, req, res) end + elseif + attached {WSF_STRING} req.query_parameter ("view") as p_view and then + (p_view.same_string ("feed") or p_view.same_string ("feed.atom")) and then + attached feed_to_atom (p_feed_id.value, nb) as l_feed_content + then + create m.make_with_body (l_feed_content) + m.header.put_content_type ("application/atom+xml") + res.send (m) + elseif + attached {WSF_STRING} req.query_parameter ("view") as p_view and then + (p_view.same_string ("feed.rss")) and then + attached feed_to_rss (p_feed_id.value, nb) as l_feed_content + then + create m.make_with_body (l_feed_content) + m.header.put_content_type ("application/rss+xml") + res.send (m) else create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api) create s.make_empty @@ -130,13 +147,29 @@ feature -- Handle s.append (ic.item) s.append ("%">") s.append (ic.item) - s.append ("") + s.append ("") + if + attached l_agg.included_categories_per_feed as tb and then + attached tb.item (ic.item) as l_cats + then + s.append ("") + across + l_cats as cats_ic + loop + s.append (" [") + s.append (r.html_encoded (cats_ic.item)) + s.append ("]") + end + s.append ("") + end + s.append ("") end s.append ("") if attached feed_to_html (p_feed_id.value, nb, True, r) as l_html then s.append (l_html) end + append_bottom_feed_links_to (s, p_feed_id.value, r) r.set_main_content (s) r.execute @@ -252,6 +285,70 @@ feature -- Hook end end + to_adapted_feed (a_feed_api: FEED_AGGREGATOR_API; a_feed_agg: FEED_AGGREGATION; a_count: INTEGER): detachable FEED + -- Feed aggregation `a_feed_agg` adapted according to filter and `a_count`. + local + nb: INTEGER + do + if a_count = 0 then + nb := a_feed_agg.size + else + nb := a_count + end + if attached a_feed_api.aggregation_feed (a_feed_agg) as l_feed then + if attached l_feed.items as lst then + if a_feed_agg.has_category_filter then + from + lst.start + until + lst.after + loop + if nb = 0 then + lst.remove + elseif a_feed_agg.is_included (lst.item_for_iteration) then + nb := nb - 1 + lst.forth + elseif a_feed_agg.is_included_for_location (lst.item_For_iteration, "") then + + else + lst.remove + end + end + elseif nb > 0 then + from + lst.start + until + lst.after + loop + if nb = 0 then + lst.remove + else + nb := nb - 1 + lst.forth + end + end + end + end + + Result := l_feed + end + end + + append_bottom_feed_links_to (s: STRING; a_feed_id: READABLE_STRING_GENERAL; a_response: CMS_RESPONSE) + do + s.append_string ("") + end + feed_to_html (a_feed_id: READABLE_STRING_GENERAL; a_count: INTEGER; with_feed_info: BOOLEAN; a_response: CMS_RESPONSE): detachable STRING local nb: INTEGER @@ -262,18 +359,21 @@ feature -- Hook vis: FEED_TO_XHTML_VISITOR s: STRING do - if attached feed_aggregator_api as l_feed_api then - if attached l_feed_api.aggregation (a_feed_id) as l_agg then - create l_cache.make (l_feed_api.cms_api.cache_location.extended (name).extended ("feed__" + a_feed_id + "__" + a_count.out + "_" + with_feed_info.out)) - Result := l_cache.item - if Result = Void or l_cache.expired (Void, l_agg.expiration) then - + if + attached feed_aggregator_api as l_feed_api and then + attached l_feed_api.aggregation (a_feed_id) as l_agg + then + create l_cache.make (l_feed_api.cms_api.cache_location.extended (name).extended ("feed__" + a_feed_id + "__" + a_count.out + "_" + with_feed_info.out)) + Result := l_cache.item + if Result = Void or l_cache.expired (Void, l_agg.expiration) then + if attached to_adapted_feed (l_feed_api, l_agg, a_count) as l_feed then create Result.make (1024) Result.append ("") create vis.make (Result) + if a_count = 0 then nb := l_agg.size else @@ -292,29 +392,72 @@ feature -- Hook vis.set_header (s) end create s.make_empty - s.append_string ("") + s.append ("
  • ") s.append_string (a_response.link ("See more ...", "feed_aggregation/" + a_response.url_encoded (a_feed_id), Void)) - s.append_string ("
  • ") + s.append ("") vis.set_footer (s) - if attached l_feed_api.aggregation_feed (l_agg) as l_feed then - if l_agg.has_category_filter and attached l_feed.items as lst then - from - lst.start - until - lst.after - loop - if not l_agg.is_included (lst.item_for_iteration) then - lst.remove - else - lst.forth - end - end - end - l_feed.accept (vis) - end + l_feed.accept (vis) l_cache.put (Result) + elseif l_cache /= Void then + l_cache.delete end + elseif l_cache /= Void then + l_cache.delete + end + end + end + + feed_to_atom (a_feed_id: READABLE_STRING_GENERAL; a_count: INTEGER): detachable STRING + local + nb: INTEGER + i: INTEGER + e: FEED_ITEM + vis: ATOM_FEED_GENERATOR + s: STRING + l_cache: CMS_FILE_STRING_8_CACHE + do + if + attached feed_aggregator_api as l_feed_api and then + attached l_feed_api.aggregation (a_feed_id) as l_agg + then + create l_cache.make (l_feed_api.cms_api.cache_location.extended (name).extended ("feed__" + a_feed_id + "__" + a_count.out + ".atom")) + Result := l_cache.item + if Result = Void or l_cache.expired (Void, l_agg.expiration) then + if attached to_adapted_feed (l_feed_api, l_agg, a_count) as l_feed then + create Result.make (1024) + create vis.make (Result) + l_feed.accept (vis) + elseif l_cache /= Void then + l_cache.delete + end + elseif l_cache /= Void then + l_cache.delete + end + end + end + + feed_to_rss (a_feed_id: READABLE_STRING_GENERAL; a_count: INTEGER): detachable STRING + local + vis: RSS_2_FEED_GENERATOR + l_cache: CMS_FILE_STRING_8_CACHE + do + if + attached feed_aggregator_api as l_feed_api and then + attached l_feed_api.aggregation (a_feed_id) as l_agg + then + create l_cache.make (l_feed_api.cms_api.cache_location.extended (name).extended ("feed__" + a_feed_id + "__" + a_count.out + ".rss")) + Result := l_cache.item + if Result = Void or l_cache.expired (Void, l_agg.expiration) then + if attached to_adapted_feed (l_feed_api, l_agg, a_count) as l_feed then + create Result.make (1024) + create vis.make (Result) + l_feed.accept (vis) + elseif l_cache /= Void then + l_cache.delete + end + elseif l_cache /= Void then + l_cache.delete end end end diff --git a/modules/feed_aggregator/site/files/css/feed_aggregator.css b/modules/feed_aggregator/site/files/css/feed_aggregator.css index d0e322e..1598658 100644 --- a/modules/feed_aggregator/site/files/css/feed_aggregator.css +++ b/modules/feed_aggregator/site/files/css/feed_aggregator.css @@ -1,3 +1,10 @@ +div.feed ul.nav { + list-style: none; +} +div.feed ul.nav li { + display: inline-block; + padding-right: 1em; +} div.feed ul { list-style: none; position: relative; diff --git a/modules/feed_aggregator/site/files/scss/feed_aggregator.scss b/modules/feed_aggregator/site/files/scss/feed_aggregator.scss index 82c2b81..6609c08 100644 --- a/modules/feed_aggregator/site/files/scss/feed_aggregator.scss +++ b/modules/feed_aggregator/site/files/scss/feed_aggregator.scss @@ -1,4 +1,11 @@ div.feed { + ul.nav { + list-style: none; + li { + display: inline-block; + padding-right: 1em; + } + } ul { list-style: none; position: relative; diff --git a/modules/messaging/src/cms_messaging_module.e b/modules/messaging/src/cms_messaging_module.e index da5f855..a25d93a 100644 --- a/modules/messaging/src/cms_messaging_module.e +++ b/modules/messaging/src/cms_messaging_module.e @@ -227,10 +227,10 @@ $(document).ready(function() { create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) r.values.force ("messaging", "messaging") r.set_main_content (new_html_messaging_form (r, api)) + r.execute else - create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make_with_permissions (req, res, api, <<"use messaging", "message any user">>) + api.response_api.send_permissions_access_denied (Void, <<"use messaging", "message any user">>, req, res) end - r.execute end handle_post_messaging (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) @@ -313,10 +313,10 @@ $(document).ready(function() { end end r.set_main_content (s) + r.execute else - create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make_with_permissions (req, res, api, <<"message any user">>) + api.response_api.send_permissions_access_denied (Void, <<"message any user">>, req, res) end - r.execute end feature {NONE} -- Helpers diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 4c39579..604f2bb 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -80,8 +80,12 @@ feature -- HTTP Methods lnk: FEED_LINK mesg: CMS_CUSTOM_RESPONSE_MESSAGE l_payload: STRING + l_feed_name: STRING_32 do - create l_feed.make (a_content_type.name) + create l_feed_name.make_from_string (api.setup.site_name) + l_feed_name.append_string ({STRING_32} " : ") + l_feed_name.append_string_general (a_content_type.name) + create l_feed.make (l_feed_name) l_feed.set_date (create {DATE_TIME}.make_now_utc) if attached {WSF_STRING} req.query_parameter ("size") as p_size and then p_size.is_integer then diff --git a/modules/recent_changes/cms_recent_changes_module.e b/modules/recent_changes/cms_recent_changes_module.e index e976dac..d3c6c2e 100644 --- a/modules/recent_changes/cms_recent_changes_module.e +++ b/modules/recent_changes/cms_recent_changes_module.e @@ -52,6 +52,7 @@ feature -- Access: router do a_router.handle ("/recent_changes/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_recent_changes (a_api, ?, ?)), a_router.methods_head_get) a_router.handle ("/recent_changes/feed", create {WSF_URI_AGENT_HANDLER}.make (agent handle_recent_changes_feed (a_api, ?, ?)), a_router.methods_head_get) + a_router.handle ("/recent_changes/feed.{format}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_recent_changes_feed (a_api, ?, ?)), a_router.methods_head_get) end feature -- Hook @@ -104,6 +105,7 @@ feature -- Hook ch: CMS_RECENT_CHANGE_ITEM l_user: detachable CMS_USER l_feed: FEED + l_feed_name: STRING_32 l_feed_item: FEED_ITEM lnk: FEED_LINK nb: NATURAL_32 @@ -127,7 +129,9 @@ feature -- Hook end end end - create l_feed.make ("CMS Recent changes") + create l_feed_name.make_from_string (a_response.api.setup.site_name) + l_feed_name.append_string ({STRING_32} " : recent changes") + create l_feed.make (l_feed_name) l_feed.set_date (create {DATE_TIME}.make_now_utc) nb := a_size across @@ -197,10 +201,22 @@ feature -- Handler l_size := 25 end + create mesg.make ({HTTP_STATUS_CODE}.ok) + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create l_content.make (1024) - recent_changes_feed (r, l_size, l_filter_source).accept (create {ATOM_FEED_GENERATOR}.make (l_content)) - create mesg.make ({HTTP_STATUS_CODE}.ok) + if + attached {WSF_STRING} req.path_parameter ("format") as p_format and then + p_format.same_string ("rss") + then + mesg.header.put_content_type ("application/rss+xml") + + recent_changes_feed (r, l_size, l_filter_source).accept (create {RSS_2_FEED_GENERATOR}.make (l_content)) + else + mesg.header.put_content_type ("application/atom+xml") + + recent_changes_feed (r, l_size, l_filter_source).accept (create {ATOM_FEED_GENERATOR}.make (l_content)) + end mesg.set_payload (l_content) res.send (mesg) end