Removed obsolete calls, harmonized predefine response, added non admin user pages.
When access is denied, also provide when possible and wanted, the needed
permissions so that in the future, user will be able to ask for
permission easily.
Renamed previous user handlers as admin user handlers.
Added non admin user handler /user/{uid} .
Add new `send_...` response to `CMS_API.response_api`, and use them
instead of `create {...RESPONSE}.... ; execute`.
Fixed potential issue with storage mailer initialization if folder does
not exist.
Added utf_8_encoded helpers function on CMS_API interface.
Fixed a few unicode potential issues.
Removed a few obsolete calls.
This commit is contained in:
@@ -87,7 +87,7 @@ feature -- Access
|
||||
do
|
||||
if attached text_item (a_name) as s then
|
||||
if s.is_valid_as_string_8 then
|
||||
Result := s.as_string_8
|
||||
Result := s.to_string_8
|
||||
else
|
||||
Result := utf.escaped_utf_32_string_to_utf_8_string_8 (s)
|
||||
end
|
||||
@@ -101,10 +101,11 @@ feature -- Access
|
||||
l_chain: NOTIFICATION_CHAIN_MAILER
|
||||
l_storage_mailer: NOTIFICATION_STORAGE_MAILER
|
||||
l_mailer: detachable NOTIFICATION_MAILER
|
||||
b: BOOLEAN
|
||||
do
|
||||
if not retried then
|
||||
if attached text_item ("mailer.smtp") as l_smtp then
|
||||
create {NOTIFICATION_SMTP_MAILER} l_mailer.make (l_smtp.as_string_8_conversion)
|
||||
if attached text_item ("mailer.smtp") as l_smtp and then l_smtp.is_valid_as_string_8 then
|
||||
create {NOTIFICATION_SMTP_MAILER} l_mailer.make (l_smtp.to_string_8)
|
||||
elseif attached text_item ("mailer.sendmail") as l_sendmail then
|
||||
create {NOTIFICATION_SENDMAIL_MAILER} l_mailer.make_with_location (l_sendmail)
|
||||
end
|
||||
@@ -120,19 +121,24 @@ feature -- Access
|
||||
if f.exists and then f.is_directory then
|
||||
create {NOTIFICATION_STORAGE_MAILER} l_storage_mailer.make (create {NOTIFICATION_EMAIL_DIRECTORY_STORAGE}.make (f.path))
|
||||
else
|
||||
if not f.exists then
|
||||
f.create_read_write
|
||||
f.close
|
||||
if f.exists then
|
||||
b := True
|
||||
else
|
||||
b := (create {CMS_FILE_SYSTEM_UTILITIES}).safe_create_raw_file (f.path)
|
||||
end
|
||||
if b then
|
||||
create {NOTIFICATION_STORAGE_MAILER} l_storage_mailer.make (create {NOTIFICATION_EMAIL_FILE_STORAGE}.make (f))
|
||||
end
|
||||
create {NOTIFICATION_STORAGE_MAILER} l_storage_mailer.make (create {NOTIFICATION_EMAIL_FILE_STORAGE}.make (f))
|
||||
end
|
||||
end
|
||||
if l_mailer /= Void then
|
||||
create l_chain.make (l_mailer)
|
||||
l_chain.set_next (l_storage_mailer)
|
||||
l_mailer := l_chain
|
||||
else
|
||||
elseif l_storage_mailer /= Void then
|
||||
l_mailer := l_storage_mailer
|
||||
else
|
||||
create {NOTIFICATION_NULL_MAILER} l_mailer
|
||||
end
|
||||
elseif l_mailer = Void then
|
||||
create {NOTIFICATION_STORAGE_MAILER} l_mailer.make (create {NOTIFICATION_EMAIL_FILE_STORAGE}.make (io.error))
|
||||
|
||||
@@ -21,6 +21,14 @@ inherit
|
||||
|
||||
feature -- Encoders
|
||||
|
||||
utf_8_encoded (a_string: READABLE_STRING_GENERAL): STRING_8
|
||||
-- `a_string' encoded using UTF-8.
|
||||
local
|
||||
utf: UTF_CONVERTER
|
||||
do
|
||||
Result := utf.utf_32_string_to_utf_8_string_8 (a_string)
|
||||
end
|
||||
|
||||
html_encoded (a_string: READABLE_STRING_GENERAL): STRING_8
|
||||
-- `a_string' encoded for html output.
|
||||
do
|
||||
@@ -36,7 +44,7 @@ feature -- Encoders
|
||||
Result := ""
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
url_encoded,
|
||||
percent_encoded (a_string: READABLE_STRING_GENERAL): STRING_8
|
||||
-- `a_string' encoded with percent encoding, mainly used for url.
|
||||
@@ -45,6 +53,6 @@ feature -- Encoders
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -75,7 +75,7 @@ feature -- URL aliases
|
||||
do
|
||||
end
|
||||
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
source_of_path_alias (a_alias: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
||||
-- Source path for alias `a_alias'.
|
||||
do
|
||||
end
|
||||
@@ -136,6 +136,6 @@ feature -- Custom
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ feature -- URL aliases
|
||||
deferred
|
||||
end
|
||||
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
source_of_path_alias (a_alias: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
||||
-- Source path for alias `a_alias'.
|
||||
deferred
|
||||
end
|
||||
@@ -89,6 +89,6 @@ feature -- Misc
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -123,7 +123,7 @@ feature -- URL aliases
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
source_of_path_alias (a_alias: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
|
||||
@@ -642,7 +642,7 @@ feature -- Status Report
|
||||
|
||||
feature -- Logging
|
||||
|
||||
logs (a_category: detachable READABLE_STRING_8; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_LOG]
|
||||
logs (a_category: detachable READABLE_STRING_GENERAL; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_LOG]
|
||||
-- List of recent logs from `a_lower' to `a_lower+a_count'.
|
||||
-- If `a_category' is set, filter to return only associated logs.
|
||||
-- If `a_count' <= 0 then, return all logs.
|
||||
@@ -1001,6 +1001,19 @@ feature -- Access: API
|
||||
Result := l_api
|
||||
end
|
||||
|
||||
response_api: CMS_RESPONSE_API
|
||||
-- API to send predefined cms responses.
|
||||
local
|
||||
l_api: like internal_response_api
|
||||
do
|
||||
l_api := internal_response_api
|
||||
if l_api = Void then
|
||||
create l_api.make (Current)
|
||||
internal_response_api := l_api
|
||||
end
|
||||
Result := l_api
|
||||
end
|
||||
|
||||
feature -- Hooks
|
||||
|
||||
setup_core_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
|
||||
@@ -1014,9 +1027,9 @@ feature -- Hooks
|
||||
|
||||
feature -- Path aliases
|
||||
|
||||
is_valid_path_alias (a_alias: READABLE_STRING_8): BOOLEAN
|
||||
is_valid_path_alias (a_alias: READABLE_STRING_GENERAL): BOOLEAN
|
||||
do
|
||||
Result := a_alias.is_empty or else not a_alias.starts_with_general ("/")
|
||||
Result := a_alias.is_empty or else not a_alias.starts_with ("/")
|
||||
end
|
||||
|
||||
set_path_alias (a_source, a_alias: READABLE_STRING_8; a_keep_previous: BOOLEAN)
|
||||
@@ -1076,7 +1089,7 @@ feature -- Path aliases
|
||||
end
|
||||
end
|
||||
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
source_of_path_alias (a_alias: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
||||
-- Resolved path for alias `a_alias'.
|
||||
--| the CMS supports aliases for path, and then this function simply returns
|
||||
--| the effective target path/url for this `a_alias'.
|
||||
@@ -1106,6 +1119,9 @@ feature {NONE}-- Implementation
|
||||
internal_user_api: detachable like user_api
|
||||
-- Cached value for `user_api`.
|
||||
|
||||
internal_response_api: detachable like response_api
|
||||
-- Cached value for `response_api`.
|
||||
|
||||
feature -- Environment/ theme
|
||||
|
||||
site_location: PATH
|
||||
|
||||
@@ -196,24 +196,24 @@ feature -- Settings: router
|
||||
local
|
||||
fhdl: WSF_FILE_SYSTEM_HANDLER
|
||||
themehdl: CMS_THEME_FILE_SYSTEM_HANDLER
|
||||
l_not_found_handler_agent: PROCEDURE [READABLE_STRING_8, WSF_REQUEST, WSF_RESPONSE]
|
||||
do
|
||||
api.logger.put_information (generator + ".configure_api_file_handler", Void)
|
||||
|
||||
create themehdl.make (api)
|
||||
themehdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||
l_not_found_handler_agent := agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||
do
|
||||
execute_default (ia_req, ia_res)
|
||||
end)
|
||||
end
|
||||
|
||||
create themehdl.make (api)
|
||||
themehdl.set_not_found_handler (l_not_found_handler_agent)
|
||||
-- See CMS_API.api.theme_path_for (...) for the hardcoded "/theme/" path.
|
||||
a_router.handle ("/theme/{theme_id}{/vars}", themehdl, router.methods_GET)
|
||||
|
||||
-- "/files/.."
|
||||
create fhdl.make_hidden_with_path (api.files_location)
|
||||
fhdl.disable_index
|
||||
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||
do
|
||||
execute_default (ia_req, ia_res)
|
||||
end)
|
||||
fhdl.set_not_found_handler (l_not_found_handler_agent)
|
||||
a_router.handle (api.files_path, fhdl, router.methods_GET)
|
||||
|
||||
-- files folder from specific module.
|
||||
@@ -222,10 +222,7 @@ feature -- Settings: router
|
||||
-- www folder. Should we keep this??
|
||||
create fhdl.make_hidden_with_path (setup.environment.www_path)
|
||||
fhdl.disable_index
|
||||
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||
do
|
||||
execute_default (ia_req, ia_res)
|
||||
end)
|
||||
fhdl.set_not_found_handler (l_not_found_handler_agent)
|
||||
a_router.handle ("/", fhdl, router.methods_GET)
|
||||
end
|
||||
|
||||
@@ -328,7 +325,6 @@ feature -- Execution
|
||||
local
|
||||
ut: FILE_UTILITIES
|
||||
p: PATH
|
||||
r: NOT_FOUND_ERROR_CMS_RESPONSE
|
||||
f: WSF_FILE_RESPONSE
|
||||
do
|
||||
p := api.theme_assets_location.extended ("favicon.ico")
|
||||
@@ -337,8 +333,7 @@ feature -- Execution
|
||||
f.set_expires_in_seconds (86_400) -- 24h = 60 sec * 60 min * 24 = 86 400 minutes
|
||||
res.send (f)
|
||||
else
|
||||
create r.make (req, res, api)
|
||||
r.execute
|
||||
api.response_api.send_not_found (Void, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -347,7 +342,6 @@ feature -- Execution
|
||||
-- i.e: "/module/{modname}/files{/vars}"
|
||||
local
|
||||
fhdl: WSF_FILE_SYSTEM_HANDLER
|
||||
r: NOT_FOUND_ERROR_CMS_RESPONSE
|
||||
do
|
||||
if attached {WSF_STRING} req.path_parameter ("modname") as l_mod_name then
|
||||
create fhdl.make_with_path (api.module_location_by_name (l_mod_name.url_encoded_value).extended ("files"))
|
||||
@@ -358,19 +352,15 @@ feature -- Execution
|
||||
end)
|
||||
fhdl.execute_starts_with ("/module/" + l_mod_name.url_encoded_value + "/files/", req, res)
|
||||
else
|
||||
create r.make (req, res, api)
|
||||
r.execute
|
||||
api.response_api.send_not_found (Void, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Default request handler if no other are relevant
|
||||
local
|
||||
r: NOT_FOUND_ERROR_CMS_RESPONSE
|
||||
do
|
||||
to_implement ("Default response for CMS_SERVICE")
|
||||
create r.make (req, res, api)
|
||||
r.execute
|
||||
api.response_api.send_not_found (Void, req, res)
|
||||
end
|
||||
|
||||
note
|
||||
|
||||
@@ -6,7 +6,7 @@ note
|
||||
class
|
||||
CMS_FILE_SYSTEM_UTILITIES
|
||||
|
||||
feature -- Files
|
||||
feature -- File path
|
||||
|
||||
relative_path_inside (a_path: PATH; a_root_path: PATH): detachable PATH
|
||||
-- Relative path from `a_root_path` to `a_path`, or Void if `a_path` is not inside `a_root_path`.
|
||||
@@ -43,6 +43,8 @@ feature -- Files
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Read
|
||||
|
||||
files_from_location (a_loc: PATH; is_recursive: BOOLEAN): detachable LIST [PATH]
|
||||
local
|
||||
d: DIRECTORY
|
||||
@@ -82,13 +84,14 @@ feature -- Files
|
||||
retry
|
||||
end
|
||||
|
||||
feature -- Read/Write
|
||||
|
||||
safe_copy_file (src,dst: PATH): BOOLEAN
|
||||
-- Copy file from `src` to `dst'
|
||||
-- and return True on success, False on failure.
|
||||
local
|
||||
retried: BOOLEAN
|
||||
f_src, f_dst: RAW_FILE
|
||||
d: DIRECTORY
|
||||
do
|
||||
Result := False
|
||||
if retried then
|
||||
@@ -96,20 +99,45 @@ feature -- Files
|
||||
else
|
||||
create f_src.make_with_path (src)
|
||||
if f_src.exists and then f_src.is_access_readable then
|
||||
if attached dst.parent as l_parent then
|
||||
create d.make_with_path (l_parent)
|
||||
if not d.exists then
|
||||
d.recursive_create_dir
|
||||
if safe_create_parent_directory (dst) then
|
||||
create f_dst.make_with_path (dst)
|
||||
if not f_dst.exists or else f_dst.is_access_writable then
|
||||
f_src.open_read
|
||||
f_dst.open_write
|
||||
f_src.copy_to (f_dst)
|
||||
f_dst.close
|
||||
f_src.close
|
||||
Result := True -- Succeed!
|
||||
end
|
||||
else
|
||||
Result := False -- No parent directory!
|
||||
end
|
||||
create f_dst.make_with_path (dst)
|
||||
if not f_dst.exists or else f_dst.is_access_writable then
|
||||
f_src.open_read
|
||||
f_dst.open_write
|
||||
f_src.copy_to (f_dst)
|
||||
f_dst.close
|
||||
f_src.close
|
||||
Result := True -- Succeed!
|
||||
end
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
feature -- Create
|
||||
|
||||
safe_create_raw_file (p: PATH): BOOLEAN
|
||||
-- Create file at `p`
|
||||
-- and return True on success or if file already exists, False on failure.
|
||||
local
|
||||
retried: BOOLEAN
|
||||
f: RAW_FILE
|
||||
do
|
||||
Result := False
|
||||
if not retried then
|
||||
if safe_create_parent_directory (p) then
|
||||
create f.make_with_path (p)
|
||||
if f.exists then
|
||||
Result := True
|
||||
else
|
||||
f.create_read_write
|
||||
f.close
|
||||
Result := f.exists
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -118,6 +146,28 @@ feature -- Files
|
||||
retry
|
||||
end
|
||||
|
||||
safe_create_parent_directory (p: PATH): BOOLEAN
|
||||
-- Create parent directory of `p`
|
||||
-- and return True on success or if parent already exists, False on failure.
|
||||
local
|
||||
retried: BOOLEAN
|
||||
d: DIRECTORY
|
||||
do
|
||||
Result := False
|
||||
if not retried then
|
||||
create d.make_with_path (p.parent)
|
||||
if d.exists then
|
||||
Result := True
|
||||
else
|
||||
d.recursive_create_dir
|
||||
Result := d.exists
|
||||
end
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -45,7 +45,10 @@ feature -- HTTP Methods
|
||||
lst: ARRAYED_LIST [CMS_MODULE]
|
||||
l_access: detachable READABLE_STRING_8
|
||||
l_denied: BOOLEAN
|
||||
l_is_fresh_installation: BOOLEAN
|
||||
do
|
||||
l_is_fresh_installation := api.enabled_modules.count <= 1 --| Should have at least the required Core module!
|
||||
|
||||
--| FIXME: improve the installer.
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||
l_access := api.setup.string_8_item ("admin.installation_access")
|
||||
@@ -62,8 +65,7 @@ feature -- HTTP Methods
|
||||
l_denied := True
|
||||
end
|
||||
if l_denied then
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||
r.set_main_content ("You do not have permission to access CMS installation procedure!")
|
||||
send_custom_access_denied ("You do not have permission to access CMS installation procedure!", Void, req, res)
|
||||
else
|
||||
create s.make_from_string ("<h1>Modules</h1><ul>")
|
||||
create lst.make (1)
|
||||
@@ -107,9 +109,14 @@ feature -- HTTP Methods
|
||||
s.append ("</ul>")
|
||||
s.append ("<div>Back to the " + r.link ("Administration", api.administration_path (Void), Void) + " ...</div>")
|
||||
r.set_main_content (s)
|
||||
|
||||
if l_is_fresh_installation then
|
||||
r.set_title (r.translation ("New installation ...", Void))
|
||||
else
|
||||
r.set_title (r.translation ("Update installation ...", Void))
|
||||
end
|
||||
r.execute
|
||||
end
|
||||
r.set_title (r.translation ("CMS Installation ...", Void))
|
||||
r.execute
|
||||
end
|
||||
|
||||
note
|
||||
|
||||
@@ -29,7 +29,7 @@ feature -- API Service
|
||||
|
||||
api: CMS_API
|
||||
|
||||
feature -- Response helpers
|
||||
feature -- Response message helpers
|
||||
|
||||
redirect_to (a_location: READABLE_STRING_8; res: WSF_RESPONSE)
|
||||
-- Send via `res' a redirection message for location `a_location'.
|
||||
@@ -56,46 +56,39 @@ feature -- Response helpers
|
||||
res.send (create {CMS_FORBIDDEN_RESPONSE_MESSAGE}.make)
|
||||
end
|
||||
|
||||
feature -- Response helpers
|
||||
|
||||
send_access_denied (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Forbidden response.
|
||||
local
|
||||
r: CMS_RESPONSE
|
||||
do
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||
r.execute
|
||||
api.response_api.send_access_denied (Void, req, res)
|
||||
end
|
||||
|
||||
send_custom_access_denied (a_message: detachable READABLE_STRING_8; a_perms: detachable ITERABLE [READABLE_STRING_8]; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Forbidden response with custom message `a_message`.
|
||||
do
|
||||
api.response_api.send_permissions_access_denied (a_message, a_perms, req, res)
|
||||
end
|
||||
|
||||
send_not_found (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Send via `res' a not found response.
|
||||
local
|
||||
r: CMS_RESPONSE
|
||||
do
|
||||
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||
r.execute
|
||||
api.response_api.send_not_found (Void, req, res)
|
||||
end
|
||||
|
||||
send_bad_request (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Send via `res' a bad request response.
|
||||
local
|
||||
r: CMS_RESPONSE
|
||||
do
|
||||
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||
r.execute
|
||||
api.response_api.send_bad_request (Void, req, res)
|
||||
end
|
||||
|
||||
send_not_implemented (a_message: detachable READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Send via `res' a not implemented response.
|
||||
local
|
||||
r: CMS_RESPONSE
|
||||
do
|
||||
create {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||
if a_message /= Void then
|
||||
r.set_main_content (a_message)
|
||||
end
|
||||
r.execute
|
||||
api.response_api.send_not_implemented (a_message, req, res)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -28,7 +28,6 @@ feature -- Execution
|
||||
-- Execute `req' responding in `res'.
|
||||
local
|
||||
fhdl: WSF_FILE_SYSTEM_HANDLER
|
||||
not_found: NOT_FOUND_ERROR_CMS_RESPONSE
|
||||
do
|
||||
if attached {WSF_STRING} req.path_parameter ("theme_id") as l_theme_id then
|
||||
create fhdl.make_hidden_with_path (api.theme_assets_location_for (l_theme_id.value))
|
||||
@@ -39,8 +38,7 @@ feature -- Execution
|
||||
elseif attached not_found_handler as h then
|
||||
h.call (req.percent_encoded_path_info, req, res)
|
||||
else
|
||||
create not_found.make (req, res, api)
|
||||
not_found.execute
|
||||
api.response_api.send_not_found (Void, req, res)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -460,7 +460,7 @@ feature -- Blocks initialization
|
||||
block_region_preference (a_block_id: READABLE_STRING_8; a_default_region: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Region associated with `a_block_id' in configuration, if any.
|
||||
do
|
||||
Result := setup.text_item_or_default ("blocks." + a_block_id + ".region", a_default_region).as_string_8_conversion
|
||||
Result := setup.string_8_item_or_default ("blocks." + a_block_id + ".region", a_default_region)
|
||||
end
|
||||
|
||||
feature -- Block management
|
||||
@@ -1119,9 +1119,14 @@ feature -- Generation
|
||||
add_to_primary_menu (lnk)
|
||||
api.hooks.invoke_menu_system_alter (menu_system, Current)
|
||||
|
||||
if api.enabled_modules.count = 1 then
|
||||
if api.enabled_modules.count <= 1 then
|
||||
-- It is the required CMS_CORE_MODULE!
|
||||
add_to_primary_menu (api.administration_link ("Install", "install"))
|
||||
lnk := api.administration_link ("Install", "install")
|
||||
if lnk.location.same_string (location) then
|
||||
-- We are on the Install page!
|
||||
else
|
||||
add_to_primary_menu (lnk)
|
||||
end
|
||||
end
|
||||
|
||||
-- Blocks
|
||||
@@ -1454,7 +1459,6 @@ feature {NONE} -- Execution
|
||||
local
|
||||
cms_page: CMS_HTML_PAGE
|
||||
page: CMS_HTML_PAGE_RESPONSE
|
||||
utf: UTF_CONVERTER
|
||||
h: HTTP_HEADER
|
||||
l_new_location: detachable READABLE_STRING_8
|
||||
l_redirection_delay: like redirection_delay
|
||||
@@ -1473,7 +1477,7 @@ feature {NONE} -- Execution
|
||||
end
|
||||
|
||||
if attached {READABLE_STRING_GENERAL} optional_content_type as l_type then
|
||||
create cms_page.make_typed (utf.utf_32_string_to_utf_8_string_8 (l_type))
|
||||
create cms_page.make_typed (api.utf_8_encoded (l_type))
|
||||
else
|
||||
create cms_page.make
|
||||
end
|
||||
|
||||
87
src/service/response/cms_response_api.e
Normal file
87
src/service/response/cms_response_api.e
Normal file
@@ -0,0 +1,87 @@
|
||||
note
|
||||
description: "[
|
||||
CMS Response API to send predefined CMS Response.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_RESPONSE_API
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_api: CMS_API)
|
||||
do
|
||||
cms_api := a_api
|
||||
end
|
||||
|
||||
cms_api: CMS_API
|
||||
|
||||
feature -- Response helpers
|
||||
|
||||
send_access_denied (a_message: detachable READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Forbidden response with custom message `a_message`.
|
||||
local
|
||||
r: FORBIDDEN_ERROR_CMS_RESPONSE
|
||||
do
|
||||
create r.make (req, res, cms_api)
|
||||
impl_response_execute (r, a_message)
|
||||
end
|
||||
|
||||
send_permissions_access_denied (a_message: detachable READABLE_STRING_8; a_perms: detachable ITERABLE [READABLE_STRING_8]; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Forbidden response with custom message `a_message` and associated permissions `a_perms`.
|
||||
local
|
||||
r: FORBIDDEN_ERROR_CMS_RESPONSE
|
||||
do
|
||||
if a_perms = Void then
|
||||
create r.make (req, res, cms_api)
|
||||
else
|
||||
create r.make_with_permissions (req, res, cms_api, a_perms)
|
||||
end
|
||||
impl_response_execute (r, a_message)
|
||||
end
|
||||
|
||||
send_not_found (a_message: detachable READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Send via `res' a not found response.
|
||||
local
|
||||
r: NOT_FOUND_ERROR_CMS_RESPONSE
|
||||
do
|
||||
create r.make (req, res, cms_api)
|
||||
impl_response_execute (r, a_message)
|
||||
end
|
||||
|
||||
send_bad_request (a_message: detachable READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Send via `res' a bad request response.
|
||||
local
|
||||
r: BAD_REQUEST_ERROR_CMS_RESPONSE
|
||||
do
|
||||
create r.make (req, res, cms_api)
|
||||
impl_response_execute (r, a_message)
|
||||
end
|
||||
|
||||
send_not_implemented (a_message: detachable READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Send via `res' a not implemented response.
|
||||
local
|
||||
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
|
||||
do
|
||||
create r.make (req, res, cms_api)
|
||||
impl_response_execute (r, a_message)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
impl_response_execute (a_response: CMS_RESPONSE; a_message: detachable READABLE_STRING_8)
|
||||
do
|
||||
if a_message /= Void then
|
||||
a_response.set_main_content (a_message)
|
||||
end
|
||||
a_response.execute
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
@@ -14,7 +14,16 @@ inherit
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
make,
|
||||
make_with_permissions
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_with_permissions (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api; a_perms: ITERABLE [READABLE_STRING_8])
|
||||
do
|
||||
make (req, res, a_api)
|
||||
set_associated_permissions (a_perms)
|
||||
end
|
||||
|
||||
feature -- Generation
|
||||
|
||||
@@ -26,17 +35,75 @@ feature -- Generation
|
||||
page.register_variable (status_code.out, "code")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
associated_permissions: detachable ARRAYED_LIST [READABLE_STRING_8]
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
set_associated_permissions (a_perms: ITERABLE [READABLE_STRING_8])
|
||||
local
|
||||
lst: like associated_permissions
|
||||
do
|
||||
lst := associated_permissions
|
||||
if lst = Void then
|
||||
create lst.make (1)
|
||||
associated_permissions := lst
|
||||
end
|
||||
across
|
||||
a_perms as ic
|
||||
loop
|
||||
lst.extend (ic.item)
|
||||
end
|
||||
end
|
||||
|
||||
set_associated_permission (a_perm: READABLE_STRING_8)
|
||||
local
|
||||
lst: like associated_permissions
|
||||
do
|
||||
lst := associated_permissions
|
||||
if lst = Void then
|
||||
create lst.make (1)
|
||||
associated_permissions := lst
|
||||
end
|
||||
lst.extend (a_perm)
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
process
|
||||
-- Computed response message.
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
set_title ("Forbidden")
|
||||
set_page_title ("Forbidden")
|
||||
set_main_content ("<em>Access denied for resource <strong>" + request.request_uri + "</strong>.</em>")
|
||||
s := "<em>Access denied for resource <strong>" + request.request_uri + "</strong>.</em>"
|
||||
-- TODO: add a form to ask for missing permissions.
|
||||
-- if
|
||||
-- attached user as u and
|
||||
-- attached associated_permissions as l_permissions and then
|
||||
-- not l_permissions.is_empty
|
||||
-- then
|
||||
-- -- User signed in
|
||||
-- -- Form to request access to this resource.
|
||||
-- s.append ("Request access ...")
|
||||
-- s.append (": ")
|
||||
-- across
|
||||
-- l_permissions as ic
|
||||
-- loop
|
||||
-- s.append_character ('"')
|
||||
-- s.append (ic.item)
|
||||
-- s.append_character ('"')
|
||||
-- s.append (" ")
|
||||
-- end
|
||||
-- end
|
||||
|
||||
set_main_content (s)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
|
||||
@@ -126,6 +126,17 @@ feature -- Access: user
|
||||
Result := storage.recent_users (params.offset.to_integer_32, params.size.to_integer_32)
|
||||
end
|
||||
|
||||
admin_user: detachable CMS_USER
|
||||
-- Admin user if any.
|
||||
do
|
||||
if
|
||||
attached user_by_id (1) as u and then
|
||||
is_admin_user (u)
|
||||
then
|
||||
Result := u
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change User
|
||||
|
||||
new_user (a_user: CMS_USER)
|
||||
|
||||
@@ -47,7 +47,7 @@ feature -- Access
|
||||
page_html (page: CMS_HTML_PAGE): STRING_8
|
||||
do
|
||||
to_implement ("Add a better response message, maybe using smarty template")
|
||||
Result := "Service Unavailable"
|
||||
Result := "Service Unavailable (missing theme!)"
|
||||
end
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
|
||||
@@ -40,7 +40,6 @@ feature -- Access
|
||||
regions: ARRAY [STRING]
|
||||
local
|
||||
i: INTEGER
|
||||
utf: UTF_CONVERTER
|
||||
l_regions: like internal_regions
|
||||
do
|
||||
l_regions := internal_regions
|
||||
@@ -51,7 +50,7 @@ feature -- Access
|
||||
across
|
||||
tb as ic
|
||||
loop
|
||||
l_regions.force (utf.utf_32_string_to_utf_8_string_8 (ic.key), i) -- NOTE: UTF-8 encoded !
|
||||
l_regions.force (utf_8_encoded (ic.key), i) -- NOTE: UTF-8 encoded !
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user