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:
Jocelyn Fiat
2017-06-09 09:29:41 +02:00
parent 359344c9dd
commit 78ef7af5f8
73 changed files with 903 additions and 343 deletions

View File

@@ -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))

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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]

View File

@@ -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

View File

@@ -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

View File

@@ -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)"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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)

View File

@@ -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"

View File

@@ -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