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

@@ -183,10 +183,10 @@ feature {NONE} -- Implementation: routes
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.add_block (login_block ("login", "Wrong username", r), "content")
end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
end
r.execute
else
api.response_api.send_access_denied (Void, req, res)
end
end
feature -- Hooks configuration

View File

@@ -0,0 +1,110 @@
ul.horizontal {
li {
display: inline-block;
}
}
#header {
#primary.menu {
ul {
li {
color: #555;
a {
color: #555;
text-decoration: none;
&:hover { color: black; }
}
background-color: #fff;
padding: 10px;
margin: 0;
}
&.horizontal {
border-bottom: solid 1px #ddd;
li {
border-top: solid 3px #fff;
&:hover {
background-color: #ffe;
border-top: solid 3px #999;
}
&.active {
font-weight: bold;
border-top: solid 3px #ddd;
background-color: #ddd;
}
&.active:hover {
border-top: solid 3px blue;
}
}
}
}
}
}
#content {
margin-left: 20px;
#highlighted {
position: relative;
border: solid 1px #ddd;
background-color: #ffc;
width: 70%;
left: 15%;
right: 15%;
padding: 5px;
font-style: italic;
}
.preview {
border: solid 1px red;
}
}
.sidebar {
padding: 5px;
margin: 3px;
/* border: solid 1px #ccc; */
&#sidebar_first {
width: 250px;
position: fixed;
top: 45px;
left: 0;
bottom: 0;
width: 200px;
border-right: solid 1px #ddd;
}
&#sidebar_second {
width: 250px;
float: right;
}
&+.main {
margin-left: 200px;
}
}
#primary-tabs {
ul.horizontal {
list-style-type: none;
li {
display: inline;
padding: 2px 5px;
border: solid 1px #ccf;
}
li.active {
border-color: #99f #99f #ddd;
border-style: solid solid none;
border-width: 2px 1px 0;
padding: 2px 7px 1px;
}
}
}
#message li.error {
background-color: #f99;
border: solid 1px red;
padding: 5px 2px 5px 2px;
}
table.with_border {
thead td {
font-weight: bold;
}
td {
border: solid 1px #ccc;
padding: 2px 5px 2px 5px;
}
}

View File

@@ -0,0 +1,38 @@
{assign name="debug_enabled" value="True"/}
{if condition="$debug_enabled"}
<!-- start debug -->
{literal}
<style>
div.cms-debug>span {
position: absolute;
bottom: 5px;
right: 5px;
color: #ccc;
padding: 5px;
}
div.cms-debug:hover>span {
color: red;
}
div.cms-debug>span+ul {
display: none;
border: solid 2px red;
background-color: #ccc;
white-space: pre-wrap;
}
div.cms-debug:hover>span+ul {
display: block;
position: relative;
bottom: 5px;
left: 1%; right: 1%;
width: 98%;
}
</style>
{/literal}
<div class="cms-debug"><span>Show debug</span>
<ul>
{assign name="kpage" value="page"/}{assign name="kregions" value="regions"/}{foreach key="k" item="i" from="$page.variables"}{unless condition="$k ~ $kpage"}{unless condition="$k ~ $kregions"}<li><strong>{$k/}</strong>={htmlentities}{$i/}{/htmlentities}</li>{/unless}{/unless}
{/foreach}
</ul>
</div>
<!-- end debug -->
{/if}

View File

@@ -17,15 +17,19 @@ create
feature {NONE} -- Initialization
make (a_name: READABLE_STRING_32)
make (a_name: READABLE_STRING_GENERAL)
-- Create an object with name `a_name'.
require
a_name_not_empty: not a_name.is_whitespace
do
name := a_name
if attached {READABLE_STRING_32} a_name as n32 then
name := n32
else
name := a_name.to_string_32
end
initialize
ensure
name_set: name = a_name
name_set: name.same_string_general (a_name)
status_not_active: status = not_active
end

View File

@@ -3,17 +3,18 @@
<target name="recaptcha">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" void_safety="all">
</option>
<setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="http_client_extension" location="..\http_client_extension\http_client_extension-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf"/>
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/>
<cluster name="recaptcha" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -3,19 +3,18 @@
<target name="recaptcha">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" void_safety="none">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
<library name="http_client_extension" location="..\http_client_extension\http_client_extension.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf"/>
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
<cluster name="recaptcha" location=".\src\" recursive="true">
</cluster>
</target>

View File

@@ -98,26 +98,24 @@ feature {NONE} -- REST API
get: detachable RESPONSE
-- Reading Data
local
l_request: REQUEST
do
create l_request.make ("GET", new_uri)
Result := l_request.execute
Result := (create {REQUEST}.make ("GET", new_uri)).execute
end
feature {NONE} -- Implementation
new_uri: STRING_8
-- new uri (BaseUri?secret=secret_value&response=response_value[&remoteip=remoteip_value]
local
l_uri: URI
do
create Result.make_from_string (base_uri)
Result.append ("?secret=")
Result.append (secret)
Result.append ("&response=")
Result.append (response)
create l_uri.make_from_string (base_uri)
l_uri.add_query_parameter ("secret", secret)
l_uri.add_query_parameter ("response", response)
if attached remoteip as l_remoteip then
Result.append ("&remoteip=" + l_remoteip)
l_uri.add_query_parameter ("remoteip", l_remoteip)
end
Result := l_uri.string
end
put_error (a_code: READABLE_STRING_GENERAL)
@@ -134,7 +132,7 @@ feature {NONE} -- Implementation
end
note
copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2017 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -51,7 +51,7 @@ feature {NONE} -- Router/administration
l_roles_handler: CMS_ADMIN_ROLES_HANDLER
l_formats_handler: CMS_ADMIN_FORMATS_HANDLER
l_user_handler: CMS_USER_HANDLER
l_user_handler: CMS_ADMIN_USER_HANDLER
l_role_handler: CMS_ROLE_HANDLER
l_admin_logs_handler: CMS_LOGS_HANDLER

View File

@@ -47,10 +47,10 @@ feature -- Execution
create s.make_empty
f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
end
l_response.execute
else
send_custom_access_denied (Void, <<"admin cache">>, req, res)
end
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -77,10 +77,10 @@ feature -- Execution
create s.make_empty
f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
end
l_response.execute
else
send_custom_access_denied (Void, <<"admin cache">>, req, res)
end
end
feature -- Widget

View File

@@ -47,10 +47,10 @@ feature -- Execution
create s.make_empty
f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
end
l_response.execute
else
send_access_denied (req, res)
end
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -92,10 +92,10 @@ feature -- Execution
create s.make_empty
f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
end
l_response.execute
else
send_access_denied (req, res)
end
end
feature -- Widget

View File

@@ -64,12 +64,11 @@ feature -- HTTP Methods
local
r: CMS_RESPONSE
do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
if api.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
create {CMS_ADMIN_RESPONSE} r.make (req, res, api)
r.execute
else
r.execute
send_access_denied (req, res)
end
end
@@ -77,12 +76,11 @@ feature -- HTTP Methods
local
r: CMS_RESPONSE
do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
if api.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
create {CMS_ADMIN_RESPONSE} r.make (req, res, api)
r.execute
else
r.execute
send_access_denied (req, res)
end
end

View File

@@ -47,10 +47,10 @@ feature -- Execution
create s.make_empty
f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
end
l_response.execute
else
send_access_denied (req, res)
end
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -99,11 +99,10 @@ feature -- Execution
create s.make_empty
f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
end
l_response.execute
else
send_access_denied (req, res)
end
end
feature -- Widget

View File

@@ -60,8 +60,7 @@ feature -- Execution
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 module uninstallation procedure!")
send_custom_access_denied ("You do not have permission to access CMS module uninstallation procedure!", Void, req, res)
else
create s.make_empty
across
@@ -82,8 +81,8 @@ feature -- Execution
end
s.append (r.link ("Back to modules management", r.location, Void))
r.set_main_content (s)
end
r.execute
end
else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create s.make_empty
@@ -119,8 +118,7 @@ feature -- Execution
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 module installation procedure!")
send_custom_access_denied ("You do not have permission to access CMS module installation procedure!", Void, req, res)
else
f := modules_to_install_collection_web_form (r)
f.submit_actions.extend (agent on_installation_submit)
@@ -138,8 +136,8 @@ feature -- Execution
r.add_notice_message ("Operation on module(s) succeeded.")
r.set_redirection (r.location)
end
end
r.execute
end
elseif l_op.same_string ("Update status") then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if api.has_permission ("admin module") then
@@ -159,15 +157,12 @@ feature -- Execution
r.add_notice_message ("Operation on module(s) succeeded.")
r.set_redirection (r.location)
end
r.execute
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("You do not have permission to administrate CMS modules!")
send_custom_access_denied ("You do not have permission to administrate CMS modules!", Void, req, res)
end
r.execute
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute
send_bad_request (req, res)
end
else
do_get (req, res)

View File

@@ -81,10 +81,10 @@ feature -- Execution
s.append ("</ul>")
end
l_response.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
end
l_response.execute
else
send_access_denied (req, res)
end
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -114,11 +114,11 @@ feature -- Execution
l_response.set_redirection (l_response.location)
l_response.set_redirection_delay (3)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
l_response.set_redirection (l_response.location)
end
l_response.execute
else
send_access_denied (req, res)
-- CHECK: set redirection?
end
end
end

View File

@@ -152,8 +152,8 @@ feature -- View/edit Format
i := i + 1
l_name := f_ic.item.name
l_all_filters.force (f_ic.item, l_name)
create cb.make_with_value ("filters[" + l_name + "]", l_name)
cb.set_title (f_ic.item.title)
create cb.make_with_value ("filters[" + l_name + "]", l_name.to_string_32)
cb.set_title (f_ic.item.title.to_string_32)
cb.set_checked (True)
create hf.make_with_text ("filter_weight[" + l_name + "]", i.out)
@@ -178,8 +178,8 @@ feature -- View/edit Format
l_name := f_ic.item.name
if l_all_filters.has (l_name) then
else
create cb.make_with_value ("filters[" + l_name + "]", l_name)
cb.set_title (f_ic.item.title)
create cb.make_with_value ("filters[" + l_name + "]", l_name.to_string_32)
cb.set_title (f_ic.item.title.to_string_32)
create ftb_row.make (2)
ftb.add_row (ftb_row)
ftb_row.add_widget (cb)
@@ -195,8 +195,8 @@ feature -- View/edit Format
api.content_types as ct_ic
loop
l_name := ct_ic.item.name
create cb.make_with_value ("content_types[]", l_name)
cb.set_title (l_name)
create cb.make_with_value ("content_types[]", l_name.to_string_32)
cb.set_title (l_name.to_string_32)
if f /= Void and then ct_ic.item.has_format (f.name) then
cb.set_checked (True)
end

View File

@@ -63,7 +63,7 @@ feature -- HTTP Methods
l_logs: LIST [CMS_LOG]
l_log: CMS_LOG
r: CMS_RESPONSE
l_cat: detachable READABLE_STRING_8
l_cat: detachable READABLE_STRING_32
l_lower: INTEGER
l_count: INTEGER
b: STRING
@@ -104,11 +104,10 @@ feature -- HTTP Methods
r.set_main_content (b)
r.set_page_title ("Logs ...")
r.set_title ("Logs")
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
end
r.execute
else
send_access_denied (req, res)
end
end
end

View File

@@ -348,9 +348,9 @@ feature -- Form
fs.extend (lab)
string_sorter.sort (l_permissions)
across l_permissions as ic loop
create cb.make_with_value ("cms_permissions", ic.item)
create cb.make_with_value ("cms_permissions", ic.item.to_string_32)
cb.set_checked (across l_role_permissions as rp_ic some rp_ic.item.is_case_insensitive_equal (ic.item) end)
cb.set_title (ic.item)
cb.set_title (ic.item.to_string_32)
fs.extend (cb)
end
end
@@ -389,7 +389,7 @@ feature -- Form
update_role (a_form_data: WSF_FORM_DATA; a_role: CMS_USER_ROLE)
-- Update node `a_node' with form_data `a_form_data' for the given content type `a_content_type'.
local
l_perm: READABLE_STRING_8
l_perm: READABLE_STRING_GENERAL
do
if attached a_form_data.string_item ("op") as f_op then
if f_op.is_case_insensitive_equal_general ("Update role") then
@@ -400,16 +400,16 @@ feature -- Form
then
if attached {WSF_STRING} a_form_data.item ("cms_permissions") as u_role then
a_role.permissions.wipe_out
a_role.add_permission (u_role.value)
a_role.add_permission (api.utf_8_encoded (u_role.value)) -- TODO: utf-8 or require valid string 8?
elseif attached {WSF_MULTIPLE_STRING} a_form_data.item ("cms_permissions") as u_permissions then
a_role.permissions.wipe_out
-- Enable checked permissions.
across
u_permissions as ic
loop
l_perm := ic.item.value.as_string_8
l_perm := ic.item.value
if not l_perm.is_whitespace then
a_role.add_permission (l_perm)
a_role.add_permission (api.utf_8_encoded (l_perm)) -- TODO: utf-8 or require valid string 8?
end
end
else
@@ -421,9 +421,9 @@ feature -- Form
l_cms_perms.values as ic
loop
if attached {WSF_STRING} ic.item as p then
l_perm := p.value.as_string_8
l_perm := p.value
if not l_perm.is_whitespace then
a_role.add_permission (l_perm)
a_role.add_permission (api.utf_8_encoded (l_perm))
end
end
end

View File

@@ -81,10 +81,8 @@ feature -- HTTP Methods
l_uid: INTEGER_64
edit_response: CMS_ROLE_FORM_RESPONSE
view_response: CMS_ROLE_VIEW_RESPONSE
r: CMS_RESPONSE
do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("admin roles") then
if api.has_permission ("admin roles") then
if req.percent_encoded_path_info.ends_with_general ("/edit") then
check valid_url: req.percent_encoded_path_info.starts_with_general (api.administration_path ("/role/")) end
create edit_response.make (req, res, api)
@@ -111,18 +109,15 @@ feature -- HTTP Methods
end
end
else
r.execute
send_access_denied (req, res)
end
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
local
edit_response: CMS_ROLE_FORM_RESPONSE
r: CMS_RESPONSE
do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("admin roles") then
if api.has_permission ("admin roles") then
if req.percent_encoded_path_info.ends_with_general ("/edit") then
create edit_response.make (req, res, api)
edit_response.execute
@@ -138,7 +133,7 @@ feature -- HTTP Methods
edit_response.execute
end
else
r.execute
send_access_denied (req, res)
end
end

View File

@@ -71,7 +71,7 @@ feature -- Execution
s.append ("<div class=%"info%"> ")
s.append ("<h4>Role Information</h4>")
s.append ("<p>Role:")
s.append (a_role.name)
s.append (html_encoded (a_role.name))
s.append ("</p>")
s.append ("<h4>Permissions:</h4>")

View File

@@ -1,10 +1,10 @@
note
description: "Summary description for {CMS_USER_FORM_RESPONSE}."
description: "Summary description for {CMS_ADMIN_USER_FORM_RESPONSE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_FORM_RESPONSE
CMS_ADMIN_USER_FORM_RESPONSE
inherit
CMS_RESPONSE
@@ -324,10 +324,10 @@ feature -- Form
create fs.make
fs.set_legend ("Basic User Account Information")
fs.extend_html_text ("<div><string><label>User name </label></strong><br></div>")
fs.extend_html_text (a_user.name)
fs.extend_raw_text (a_user.name)
if attached a_user.email as l_email then
create fe.make_with_text ("email", l_email)
create fe.make_with_text ("email", l_email.to_string_32)
else
create fe.make_with_text ("email", "")
end
@@ -477,7 +477,7 @@ feature -- Form
api.user_api.user_by_email (l_email) = Void
then
-- Valid email
a_user.set_email (l_email)
a_user.set_email (api.utf_8_encoded (l_email))
else
if attached l_user.email as u_email and then not u_email.is_case_insensitive_equal_general (l_email) then
a_form_data.report_invalid_field ("email", "Email already exist!")

View File

@@ -1,12 +1,12 @@
note
description: "[
Handler for a CMS user in the CMS interface
Administration handler for a CMS user in the CMS interface
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_HANDLER
CMS_ADMIN_USER_HANDLER
inherit
CMS_HANDLER
@@ -79,12 +79,10 @@ feature -- HTTP Methods
local
l_user: detachable CMS_USER
l_uid: INTEGER_64
edit_response: CMS_USER_FORM_RESPONSE
view_response: CMS_USER_VIEW_RESPONSE
r: CMS_RESPONSE
edit_response: CMS_ADMIN_USER_FORM_RESPONSE
view_response: CMS_ADMIN_USER_VIEW_RESPONSE
do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("admin users") then
if api.has_permission ("admin users") then
if req.percent_encoded_path_info.ends_with_general ("/edit") then
check valid_url: req.percent_encoded_path_info.starts_with_general (api.administration_path ("/user/")) end
create edit_response.make (req, res, api)
@@ -111,18 +109,16 @@ feature -- HTTP Methods
end
end
else
r.execute
send_access_denied (req, res)
end
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
local
edit_response: CMS_USER_FORM_RESPONSE
r: CMS_RESPONSE
edit_response: CMS_ADMIN_USER_FORM_RESPONSE
do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("admin users") then
if api.has_permission ("admin users") then
if req.percent_encoded_path_info.ends_with_general ("/edit") then
create edit_response.make (req, res, api)
edit_response.execute
@@ -138,7 +134,7 @@ feature -- HTTP Methods
edit_response.execute
end
else
r.execute
send_access_denied (req, res)
end
end
@@ -190,7 +186,7 @@ feature {NONE} -- New User
create_new_user (req: WSF_REQUEST; res: WSF_RESPONSE)
local
edit_response: CMS_USER_FORM_RESPONSE
edit_response: CMS_ADMIN_USER_FORM_RESPONSE
do
if req.percent_encoded_path_info.starts_with (api.administration_path ("/add/user")) then
create edit_response.make (req, res, api)

View File

@@ -1,10 +1,10 @@
note
description: "Summary description for {CMS_USER_VIEW_RESPONSE}."
description: "Summary description for {CMS_ADMIN_USER_VIEW_RESPONSE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_VIEW_RESPONSE
CMS_ADMIN_USER_VIEW_RESPONSE
inherit
CMS_RESPONSE
@@ -27,7 +27,6 @@ feature -- Query
end
end
feature -- Execution
process

View File

@@ -73,8 +73,7 @@ feature -- HTTP Methods
-- get them from the configuration file and load them into
-- the setup class.
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
if l_response.has_permission ("admin users") then
if api.has_permission ("admin users") then
user_api := api.user_api
l_count := user_api.users_count
@@ -157,7 +156,7 @@ feature -- HTTP Methods
l_response.set_main_content (s)
l_response.execute
else
l_response.execute
send_access_denied (req, res)
end
end
end

View File

@@ -81,7 +81,7 @@ feature -- Basic Operations / Internal
feature -- Basic Operations / Contact
send_account_evaluation (a_user: CMS_USER; a_application, a_url_activate, a_url_reject, a_host: READABLE_STRING_8)
send_account_evaluation (a_user: CMS_USER; a_application: READABLE_STRING_GENERAL; a_url_activate, a_url_reject, a_host: READABLE_STRING_8)
-- Send new user register to webmaster to confirm or reject itt.
local
l_message: STRING
@@ -95,7 +95,7 @@ feature -- Basic Operations / Contact
else
l_message.replace_substring_all ("$email", "unknown email")
end
l_message.replace_substring_all ("$application", a_application)
l_message.replace_substring_all ("$application", cms_api.utf_8_encoded (a_application))
l_message.replace_substring_all ("$activation_url", a_url_activate)
l_message.replace_substring_all ("$rejection_url", a_url_reject)
send_message (contact_email_address, contact_email_address, parameters.contact_subject_account_evaluation, l_message)

View File

@@ -13,7 +13,6 @@ feature {NONE} -- Initialization
make (a_cms_api: CMS_API)
local
utf: UTF_CONVERTER
s: detachable READABLE_STRING_32
l_utf8_site_name: IMMUTABLE_STRING_8
l_contact_email, l_subject_register, l_subject_activate, l_subject_password, l_subject_oauth: detachable READABLE_STRING_8
@@ -31,23 +30,23 @@ feature {NONE} -- Initialization
if attached a_cms_api.module_configuration_by_name ({CMS_AUTHENTICATION_MODULE}.name, Void) as cfg then
s := cfg.text_item ("email")
if s /= Void then
l_contact_email := utf.utf_32_string_to_utf_8_string_8 (s)
l_contact_email := cms_api.utf_8_encoded (s)
end
s := cfg.text_item ("subject_register")
if s /= Void then
l_subject_register := utf.utf_32_string_to_utf_8_string_8 (s)
l_subject_register := cms_api.utf_8_encoded (s)
end
s := cfg.text_item ("subject_activate")
if s /= Void then
l_subject_register := utf.utf_32_string_to_utf_8_string_8 (s)
l_subject_register := cms_api.utf_8_encoded (s)
end
s := cfg.text_item ("subject_password")
if s /= Void then
l_subject_register := utf.utf_32_string_to_utf_8_string_8 (s)
l_subject_register := cms_api.utf_8_encoded (s)
end
s := cfg.text_item ("subject_oauth")
if s /= Void then
l_subject_oauth := utf.utf_32_string_to_utf_8_string_8 (s)
l_subject_oauth := cms_api.utf_8_encoded (s)
end
end
if l_contact_email = Void then

View File

@@ -65,6 +65,7 @@ feature -- Access
Result.force ("account reject")
Result.force ("account reactivate")
Result.force ("change own username")
Result.force ("view user")
end
feature {CMS_EXECUTION} -- Administration
@@ -123,6 +124,8 @@ feature -- Router
a_router.handle ("/account/new-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_new_password(a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/reset-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reset_password(a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/change/{field}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_change_field (a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/user/{uid}", create {CMS_USER_HANDLER}.make (a_api), a_router.methods_get)
end
feature -- Hooks configuration
@@ -382,7 +385,7 @@ feature -- Handler
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.value) 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
@@ -428,15 +431,13 @@ feature -- Handler
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("There were issue with your application, invalid or missing values.")
api.response_api.send_bad_request ("There were issue with your application, invalid or missing values.", req, res)
end
end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("You can also contact the webmaster to ask for an account.")
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
end
handle_activation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -500,8 +501,7 @@ feature -- Handler
l_ir.execute
end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute
api.response_api.send_access_denied (Void, req, res)
end
end
@@ -536,8 +536,7 @@ feature -- Handler
l_ir.execute
end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute
api.response_api.send_access_denied (Void, req, res)
end
end
@@ -551,8 +550,8 @@ feature -- Handler
l_url_reject: STRING
l_email: READABLE_STRING_8
do
if api.has_permission ("account reactivate") then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("account reactivate") then
if req.is_post_request_method then
if attached {WSF_STRING} req.form_parameter ("email") as p_email then
if p_email.value.is_valid_as_string_8 then
@@ -587,11 +586,10 @@ feature -- Handler
end
end
end
r.execute
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute
api.response_api.send_access_denied (Void, req, res)
end
r.execute
end
handle_new_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -700,7 +698,7 @@ feature -- Handler
l_fieldname := p_field.url_encoded_value
end
if l_fieldname = Void then
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
api.response_api.send_bad_request (Void, req, res)
else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
@@ -814,9 +812,9 @@ feature -- Handler
end
r.set_main_content (b)
end
end
r.execute
end
end
block_list: ITERABLE [like {CMS_BLOCK}.name]
do
@@ -1118,36 +1116,30 @@ feature -- Access: configuration
form_registration_application_description (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if attached cfg.text_item ("forms.registration.application_description") as l_desc and then not l_desc.is_whitespace then
Result := utf.utf_32_string_to_utf_8_string_8 (l_desc)
Result := api.utf_8_encoded (l_desc)
end
end
end
recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if attached cfg.text_item ("recaptcha.secret_key") as l_recaptcha_key and then not l_recaptcha_key.is_empty then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
Result := api.utf_8_encoded (l_recaptcha_key)
end
end
end
recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if attached cfg.text_item ("recaptcha.site_key") as l_recaptcha_key and then not l_recaptcha_key.is_empty then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
Result := api.utf_8_encoded (l_recaptcha_key)
end
end
end

View File

@@ -54,9 +54,8 @@ feature -- Request handling
-- get them from the configuration file and load them into
-- the setup class.
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
if
l_response.has_permission ("admin registration")
api.has_permission ("admin registration")
then
l_user_api := api.user_api
@@ -127,7 +126,7 @@ feature -- Request handling
l_response.set_main_content (s)
l_response.execute
else
l_response.execute
api.response_api.send_access_denied (Void, req, res)
end
end

View File

@@ -0,0 +1,103 @@
note
description: "[
Handler for a CMS user in the CMS interface
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_HANDLER
inherit
CMS_HANDLER
WSF_URI_HANDLER
rename
execute as uri_execute,
new_mapping as new_uri_mapping
end
WSF_URI_TEMPLATE_HANDLER
rename
execute as uri_template_execute,
new_mapping as new_uri_template_mapping
select
new_uri_template_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 (req, res)
end
uri_template_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler
do
execute (req, res)
end
feature -- Query
user_id_path_parameter (req: WSF_REQUEST): INTEGER_64
-- User id passed as path parameter for request `req'.
local
s: STRING
do
if attached {WSF_STRING} req.path_parameter ("uid") as p_nid then
s := p_nid.value
if s.is_integer_64 then
Result := s.to_integer_64
end
end
end
feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- <Precursor>
local
l_user: detachable CMS_USER
l_uid: INTEGER_64
view_response: CMS_USER_VIEW_RESPONSE
do
if api.has_permission ("view user") then
-- Display existing node
l_uid := user_id_path_parameter (req)
if l_uid > 0 then
l_user := api.user_api.user_by_id (l_uid)
if
l_user /= Void
then
create view_response.make (req, res, api)
view_response.execute
else
send_not_found (req, res)
end
else
send_bad_request (req, res)
end
else
send_access_denied (req, res)
end
end
end

View File

@@ -0,0 +1,103 @@
note
description: "Summary description for {CMS_USER_VIEW_RESPONSE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_USER_VIEW_RESPONSE
inherit
CMS_RESPONSE
create
make
feature -- Query
user_id_path_parameter (req: WSF_REQUEST): INTEGER_64
-- User id passed as path parameter for request `req'.
local
s: STRING
do
if attached {WSF_STRING} req.path_parameter ("uid") as p_nid then
s := p_nid.value
if s.is_integer_64 then
Result := s.to_integer_64
end
end
end
feature -- Process
process
-- Computed response message.
local
b: STRING_8
uid: INTEGER_64
user_api: CMS_USER_API
f: CMS_FORM
do
user_api := api.user_api
create b.make_empty
uid := user_id_path_parameter (request)
if
uid > 0 and then
attached user_api.user_by_id (uid) as l_user
then
if
api.has_permission ("view user")
or l_user.same_as (user) -- Same user
then
f := new_view_form (l_user, request.request_uri, "view-user")
f.append_to_html (wsf_theme, b)
else
b.append ("You don't have the permission to view this user!")
end
else
b.append ("User not found!")
end
set_main_content (b)
end
feature -- Process Edit
new_view_form (a_user: detachable CMS_USER; a_url: READABLE_STRING_8; a_name: STRING): CMS_FORM
-- Create a web form named `a_name' for user `a_user' (if set), using form action url `a_url'.
local
th: WSF_FORM_HIDDEN_INPUT
do
create Result.make (a_url, a_name)
create th.make ("user-id")
if a_user /= Void then
th.set_text_value (a_user.id.out)
else
th.set_text_value ("0")
end
Result.extend (th)
populate_form (Result, a_user)
end
populate_form (a_form: WSF_FORM; a_user: detachable CMS_USER)
-- Fill the web form `a_form' with data from `a_node' if set,
-- and apply this to content type `a_content_type'.
local
ti: WSF_FORM_TEXT_INPUT
fs: WSF_FORM_FIELD_SET
do
if a_user /= Void then
create fs.make
fs.set_legend ("User Information")
create ti.make_with_text ("profile_name", a_user.name)
if attached a_user.profile_name as l_profile_name then
ti.set_text_value (l_profile_name)
end
ti.set_label ("Profile name")
ti.set_is_readonly (True)
fs.extend (ti)
a_form.extend (fs)
end
end
end

View File

@@ -37,8 +37,6 @@ feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- <Precursor>
local
l_error: NOT_FOUND_ERROR_CMS_RESPONSE
do
check user_void: user = Void end
if attached user_from_request (req) as l_user then
@@ -47,13 +45,11 @@ feature -- HTTP Methods
Precursor (req, res)
else
-- Throw a bad request error because the user is not valid
create l_error.make (req, res, api)
if attached user_parameter (req) as l_user_id then
l_error.set_main_content ("<h1>Error</h1>User with id " + api.html_encoded (l_user_id) + " not found!</h1>")
api.response_api.send_not_found ("<h1>Error</h1>User with id " + api.html_encoded (l_user_id) + " not found!</h1>", req, res)
else
l_error.set_main_content ("<h1>Error</h1>User not found!</h1>")
api.response_api.send_not_found ("<h1>Error</h1>User not found!</h1>", req, res)
end
l_error.execute
end
user := Void
end

View File

@@ -123,30 +123,26 @@ feature -- Recaptcha
recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if
attached cfg.text_item ("recaptcha.secret_key") as l_recaptcha_key and then
not l_recaptcha_key.is_empty
then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
Result := api.utf_8_encoded (l_recaptcha_key)
end
end
end
recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if
attached cfg.text_item ("recaptcha.site_key") as l_recaptcha_key and then
not l_recaptcha_key.is_empty
then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
Result := api.utf_8_encoded (l_recaptcha_key)
end
end
end

View File

@@ -13,13 +13,12 @@ feature {NONE} -- Initialization
make (a_cms_api: CMS_API; a_contact_module: CMS_CONTACT_MODULE)
local
utf: UTF_CONVERTER
l_site_name: READABLE_STRING_8
s: detachable READABLE_STRING_32
l_contact_email, l_contact_subject: detachable READABLE_STRING_8
do
-- Use global smtp setting if any, otherwise "localhost"
l_site_name := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.site_name)
l_site_name := a_cms_api.utf_8_encoded (a_cms_api.setup.site_name)
admin_email := a_cms_api.setup.site_email
if not admin_email.has ('<') then
@@ -29,11 +28,11 @@ feature {NONE} -- Initialization
if attached {CONFIG_READER} a_cms_api.module_configuration (a_contact_module, Void) as cfg then
s := cfg.text_item ("email")
if s /= Void then
l_contact_email := utf.utf_32_string_to_utf_8_string_8 (s)
l_contact_email := a_cms_api.utf_8_encoded (s)
end
s := cfg.text_item ("subject")
if s /= Void then
l_contact_subject := utf.utf_32_string_to_utf_8_string_8 (s)
l_contact_subject := a_cms_api.utf_8_encoded (s)
end
end
if l_contact_email /= Void then

View File

@@ -25,7 +25,6 @@ feature -- Change
save_contact_message (m: CONTACT_MESSAGE)
local
s: STRING
utf: UTF_CONVERTER
now: DATE_TIME
do
error_handler.reset
@@ -38,7 +37,7 @@ feature -- Change
s.append (m.date.out)
s.append_character ('%N')
s.append ("name=")
s.append (utf.utf_32_string_to_utf_8_string_8 (m.username))
s.append (api.utf_8_encoded (m.username))
s.append_character ('%N')
if attached m.email as l_email then
@@ -47,7 +46,7 @@ feature -- Change
s.append_character ('%N')
end
s.append ("message=%N")
s.append (utf.utf_32_string_to_utf_8_string_8 (m.message))
s.append (api.utf_8_encoded (m.message))
s.append_character ('%N')
save_to_file (s, date_to_yyyymmdd_hhmmss_string (now))

View File

@@ -253,11 +253,19 @@ feature {NONE} -- Implementation
end
replace_substring_all (s: STRING_GENERAL; a_old: READABLE_STRING_8; a_new: STRING_GENERAL)
local
utf: UTF_CONVERTER
do
if attached {STRING_8} s as s8 then
if a_new.is_valid_as_string_8 then
s8.replace_substring_all (a_old, a_new.to_string_8)
else
check a_new_is_string_8: False end
-- Use UTF-8 for now.
s8.replace_substring_all (a_old, utf.utf_32_string_to_utf_8_string_8 (a_new))
end
elseif attached {STRING_32} s as s32 then
s32.replace_substring_all (a_old, a_new)
s32.replace_substring_all (a_old.to_string_32, a_new)
end
end

View File

@@ -35,7 +35,6 @@ feature -- Access
l_feed_id: READABLE_STRING_32
l_title: detachable READABLE_STRING_GENERAL
l_locations: detachable STRING_TABLE [READABLE_STRING_8]
utf: UTF_CONVERTER
l_table: like internal_aggregations
do
l_table := internal_aggregations
@@ -56,20 +55,20 @@ feature -- Access
across
l_location_list as loc_ic
loop
l_locations.force (utf.utf_32_string_to_utf_8_string_8 (loc_ic.item), loc_ic.item)
l_locations.force (cms_api.utf_8_encoded (loc_ic.item), loc_ic.item)
end
end
if attached cfg.text_table_item ({STRING_32} "feeds." + l_feed_id + ".locations") as l_location_table then
across
l_location_table as loc_tb_ic
loop
l_locations.force (utf.utf_32_string_to_utf_8_string_8 (loc_tb_ic.item), loc_tb_ic.key)
l_locations.force (cms_api.utf_8_encoded (loc_tb_ic.item), loc_tb_ic.key)
end
end
if
attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".location") as l_location
then
l_locations.force (utf.utf_32_string_to_utf_8_string_8 (l_location), l_location)
l_locations.force (cms_api.utf_8_encoded (l_location), l_location)
end
if l_locations /= Void and then not l_locations.is_empty then
l_title := cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".title")
@@ -93,7 +92,7 @@ feature -- Access
across
l_locations as loc_ic
loop
agg.locations.force (utf.utf_32_string_to_utf_8_string_8 (loc_ic.item))
agg.locations.force (cms_api.utf_8_encoded (loc_ic.item))
end
Result.force (agg, l_feed_id)
if attached cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + ".categories") as l_cats then

View File

@@ -98,8 +98,7 @@ feature -- Handle
m.header.put_content_type_text_html
res.send (m)
else
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, a_api)
r.execute
a_api.response_api.send_not_found (Void, req, res)
end
else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api)
@@ -143,8 +142,7 @@ feature -- Handle
r.execute
end
else
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, a_api)
r.execute
a_api.response_api.send_not_found (Void, req, res)
end
else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api)
@@ -199,7 +197,6 @@ feature -- Hook
-- List of block names, managed by current object.
local
res: ARRAYED_LIST [like {CMS_BLOCK}.name]
utf_conv: UTF_CONVERTER
do
if
attached feed_aggregator_api as l_feed_api and then
@@ -209,7 +206,7 @@ feature -- Hook
across
l_aggs as ic
loop
res.force ("?feed." + utf_conv.utf_32_string_to_utf_8_string_8 (ic.item))
res.force ("?feed." + utf_8_encoded (ic.item))
end
else
create res.make (0)

View File

@@ -140,8 +140,8 @@ feature -- Handler
do
check req.is_get_request_method end
if not api.has_permission (browse_files_permission) then
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.add_error_message ("You are not allowed to browse CMS files!")
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make_with_permissions (req, res, api, <<browse_files_permission>>)
r.add_error_message ("You are not allowed to browse files!")
elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
@@ -276,7 +276,7 @@ feature -- Handler
body.append ("<form action=%"" + r.url (uploads_location, Void) + "%" class=%"dropzone%">")
body.append ("</form>%N")
body.append ("<a href=%""+ r.url (uploads_location, Void) +"?basic_upload=yes%">Use basic file uploading.</a>%N")
body.append ("<a href=%""+ r.url (uploads_location, Void) + "?basic_upload=yes%">Use basic file uploading.</a>%N")
end
body.append ("</div>")
end
@@ -284,15 +284,15 @@ feature -- Handler
if req.is_get_head_request_method then
-- Build the response.
if r.has_permission (browse_files_permission) then
body.append ("<br/><div class=%"center%"><a class=%"button%" href=%""+ r.url (uploads_location, Void) +"%">Refresh uploaded</a></div>")
body.append ("<br/><div class=%"center%"><a class=%"button%" href=%"" + r.url (uploads_location, Void) + "%">Refresh uploaded</a></div>")
append_uploaded_file_album_to (req, api, body)
else
r.add_warning_message ("You are not allowed to browse files!")
end
end
r.set_main_content (body)
r.execute
elseif req.is_post_request_method then
if api.has_permission (upload_files_permission) then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
@@ -305,14 +305,13 @@ feature -- Handler
r.set_redirection (r.url (uploads_location, Void))
end
r.set_main_content (body)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("You are not allowed to upload file!")
end
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
end
r.execute
else
api.response_api.send_permissions_access_denied ("You are not allowed to upload file!", <<upload_files_permission>>, req, res)
end
else
api.response_api.send_bad_request (Void, req, res)
end
end
process_uploaded_files (req: WSF_REQUEST; api: CMS_API; a_output: STRING)
@@ -472,7 +471,7 @@ feature -- Handler
do
if attached files_api as l_files_api then
if not api.has_permission (admin_files_permission) then
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make_with_permissions (req, res, api, <<admin_files_permission>>)
r.add_error_message ("You are not allowed to remove file!")
elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)

View File

@@ -83,14 +83,16 @@ feature -- Element change
-- sets `a_number' after the name. This is done when the file was already uploaded
local
position: INTEGER_32
new_name: STRING_8
new_name: STRING_32
l_uploaded_file_string_representation: READABLE_STRING_32
do
position := uploaded_file.string_representation.index_of ('.', 1)
l_uploaded_file_string_representation := uploaded_file.string_representation
position := l_uploaded_file_string_representation.index_of ('.', 1)
create new_name.make_empty
new_name := uploaded_file.string_representation.head (position-1)
new_name.append ("_(" + a_number.out + ")")
new_name.append (uploaded_file.string_representation.substring (position, uploaded_file.string_representation.count))
new_name := l_uploaded_file_string_representation.head (position-1)
new_name.append_string_general ("_(" + a_number.out + ")")
new_name.append (l_uploaded_file_string_representation.substring (position, l_uploaded_file_string_representation.count))
location := uploads_directory.extended (new_name)
end

View File

@@ -57,15 +57,13 @@ 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)
Result := api.utf_8_encoded (l_gcse_cx_key)
end
end
end

View File

@@ -223,12 +223,12 @@ $(document).ready(function() {
local
r: CMS_RESPONSE
do
if api.has_permission ("use messaging") or api.has_permission ("message any user") then
if api.has_permissions (<<"use messaging", "message any user">>) then
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))
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make_with_permissions (req, res, api, <<"use messaging", "message any user">>)
end
r.execute
end
@@ -314,7 +314,7 @@ $(document).ready(function() {
end
r.set_main_content (s)
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make_with_permissions (req, res, api, <<"message any user">>)
end
r.execute
end
@@ -337,9 +337,8 @@ feature {NONE} -- Contact Message
resolved_template_text (api: CMS_API; a_text: READABLE_STRING_GENERAL; a_target_user: detachable CMS_USER): STRING_8
local
smt: CMS_SMARTY_TEMPLATE_TEXT
utf: UTF_CONVERTER
do
create smt.make (utf.utf_32_string_to_utf_8_string_8 (a_text))
create smt.make (api.utf_8_encoded (a_text))
across
api.builtin_variables as vars_ic
loop

View File

@@ -372,7 +372,7 @@ feature -- Hooks
loop
if
attached ic.item.typename as l_typename and then
across l_node_typenames as t_ic some t_ic.item.same_string (l_typename) end
across l_node_typenames as t_ic some t_ic.item.same_string_general (l_typename) end
then
if ic.item.entity.is_integer then
nid := ic.item.entity.to_integer_64

View File

@@ -142,8 +142,8 @@ feature -- Forms ...
ti.set_description ("Optionally specify an alternative URL path by which this content can be accessed.<br/>%NFor example, type 'about' when writing an about page. Use a relative path or the URL alias won't work.")
end
ti.set_text_value (l_uri)
ti.set_placeholder (l_auto_path_alias)
ti.set_text_value (l_uri.to_string_32)
ti.set_placeholder (l_auto_path_alias.to_string_32)
ti.set_validation_action (agent (fd: WSF_FORM_DATA; ia_response: NODE_RESPONSE; ia_node: detachable CMS_NODE)
do
if
@@ -204,7 +204,7 @@ feature -- Forms ...
end
-- Auto path alias / suggestion
create thi.make ("auto_path_alias")
thi.set_text_value (l_auto_path_alias)
thi.set_text_value (l_auto_path_alias.to_string_32)
thi.set_is_readonly (True)
f.insert_before (thi, w)
end

View File

@@ -241,7 +241,11 @@ feature -- Form
if attached fd.string_item ("content") as l_content then
b.append ("<strong>Content:</strong><div class=%"content%">")
if l_format /= Void then
b.append (l_format.formatted_output (l_content))
if l_content.is_valid_as_string_8 then
b.append (l_format.formatted_output (l_content.to_string_8))
else
b.append (l_format.formatted_output (api.utf_8_encoded (l_content)))
end
else
b.append (html_encoded (l_content))
end

View File

@@ -75,6 +75,14 @@ feature -- Query
end
end
feature -- Permissions
view_unpublished_permissions (a_node: CMS_NODE): ITERABLE [READABLE_STRING_8]
-- Permissions to view unpublished node `a_node`.
do
Result := <<"view unpublished " + a_node.content_type>>
end
feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -148,7 +156,7 @@ feature -- HTTP Methods
attached api.user as l_user and then
( node_api.is_author_of_node (l_user, l_node)
or else (
api.user_has_permission (l_user, "view unpublished " + l_node.content_type)
api.user_has_permissions (l_user, view_unpublished_permissions (l_node))
)
)
then
@@ -403,15 +411,10 @@ feature -- Error
send_access_denied_to_unpublished_node (req: WSF_REQUEST; res: WSF_RESPONSE; a_node: CMS_NODE)
-- Forbidden response.
local
r: CMS_RESPONSE
do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("This content is NOT published!")
r.execute
send_custom_access_denied ("This content is NOT published!", view_unpublished_permissions (a_node), req, res)
end
feature {NONE} -- Node
create_new_node (req: WSF_REQUEST; res: WSF_RESPONSE)

View File

@@ -86,8 +86,7 @@ feature -- HTTP Methods
-- l_page.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented<br/>", Void), "highlighted")
l_page.execute
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
l_page.execute
send_custom_access_denied (Void, <<"view trash", "view any trash", "view own trash">>, req, res)
end
end

View File

@@ -79,7 +79,7 @@ feature -- Access: Consumers OAuth20
Result := openid_storage.openid_consumers
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
openid_consumer_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_OPENID_CONSUMER
-- Retrieve a consumer by name `a_name', if any.
do
Result := openid_storage.openid_consumer_by_name (a_name)

View File

@@ -226,7 +226,7 @@ feature -- Hooks
create o.make (req.absolute_script_url ("/account/auth/login-with-openid"))
o.ask_email (True)
o.ask_all_info (False)
if attached o.auth_url (p_openid) as l_url then
if p_openid.is_valid_as_string_8 and then attached o.auth_url (p_openid.to_string_8) as l_url then
r.set_redirection (l_url)
else
s.append (" Failure")
@@ -248,7 +248,7 @@ feature -- Hooks
attached {WSF_STRING} req.cookie (a_openid_api.session_token) as l_cookie_token
then
-- Logout OAuth
create l_cookie.make (a_openid_api.session_token, l_cookie_token.value)
create l_cookie.make (a_openid_api.session_token, l_cookie_token.url_encoded_value)
l_cookie.set_path ("/")
l_cookie.set_max_age (-1)
res.add_cookie (l_cookie)
@@ -335,6 +335,7 @@ feature -- Openid Login
b: STRING
o: OPENID_CONSUMER
v: OPENID_CONSUMER_VALIDATION
l_email: STRING_8
do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty
@@ -346,8 +347,9 @@ feature -- Openid Login
v.validate
if v.is_valid then
if attached v.identity as l_identity and then
attached v.email_attribute as l_email
attached v.email_attribute as l_email_attrib
then
l_email := api.utf_8_encoded (l_email_attrib)
l_user_api := api.user_api
if attached l_user_api.user_by_email (l_email) as p_user then
-- User with email exist
@@ -355,7 +357,7 @@ feature -- Openid Login
-- Update openid entry?
else
-- create a oauth entry
a_openid_api.new_user_openid (l_identity,p_user)
a_openid_api.new_user_openid (l_identity, p_user)
end
create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (a_openid_api.session_max_age)
@@ -368,7 +370,7 @@ feature -- Openid Login
l_roles.force (l_user_api.authenticated_user_role)
-- Create a new user and oauth entry
create l_user.make (l_email)
create l_user.make (l_email_attrib)
l_user.set_email (l_email)
l_user.set_password (new_token) -- generate a random password.
l_user.set_roles (l_roles)

View File

@@ -37,7 +37,7 @@ feature -- Access: Consumers
deferred
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
openid_consumer_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_OPENID_CONSUMER
-- Retrieve a consumer by name `a_name', if any.
deferred
end

View File

@@ -39,7 +39,7 @@ feature -- Access: Consumers
create {ARRAYED_LIST[STRING]}Result.make(0)
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
openid_consumer_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_OPENID_CONSUMER
-- <Precursor>
do
end

View File

@@ -99,7 +99,7 @@ feature --Access: Consumers
sql_finalize
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
openid_consumer_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_OPENID_CONSUMER
-- Retrieve a consumer by name `a_name', if any.
local
l_parameters: STRING_TABLE [detachable ANY]

View File

@@ -141,7 +141,7 @@ feature -- Hook
create s.make_empty
if attached ch.information as l_information then
s.append (l_information)
s.append_string_general (l_information)
end
if attached ch.summary as sum then
if not s.is_empty then
@@ -248,9 +248,9 @@ feature -- Handler
l_size := 25
end
if api.has_permission ("view recent changes") then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("view recent changes") then
l_user := r.user
l_user := api.user
create l_changes.make (l_size, l_until_date, l_filter_source)
create l_content.make (1024)
@@ -406,11 +406,10 @@ feature -- Handler
create htdate.make_from_date_time (l_until_date)
r.set_title ("Recent changes before " + htdate.string)
end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
end
r.execute
else
api.response_api.send_permissions_access_denied (Void, <<"view recent changes">>, req, res)
end
end
feature -- Hooks configuration

View File

@@ -123,8 +123,7 @@ feature -- Handler
mesg.set_payload (l_sitemap_xml)
res.send (mesg)
else
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute
api.response_api.send_not_found (Void, req, res)
end
end
end

View File

@@ -143,11 +143,11 @@ feature -- HTTP Methods
s.append ("No entity found.")
end
l_page.set_main_content (s)
l_page.execute
else
-- Responding with `main_content_html (l_page)'.
create {NOT_FOUND_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
send_not_found (req, res)
end
l_page.execute
else
-- Responding with `main_content_html (l_page)'.
create {BAD_REQUEST_ERROR_CMS_RESPONSE} l_page.make (req, res, api)

View File

@@ -277,13 +277,13 @@ feature -- HTTP Methods
l_typename := ic.item.name
create w_cb.make_with_value ("typenames[]", api.html_encoded (l_typename))
w_cb.set_title (ic.item.name)
w_cb.set_title (ic.item.name.to_string_32)
wtb_row.set_item (create {WSF_WIDGET_TABLE_ITEM}.make_with_content (w_cb), 1)
v := Void
if
l_typenames /= Void and then
across l_typenames as tn_ic some l_typename.is_case_insensitive_equal (tn_ic.item) end
across l_typenames as tn_ic some l_typename.is_case_insensitive_equal_general (tn_ic.item) end
then
w_cb.set_checked (True)
if attached taxonomy_api.vocabularies_for_type (l_typename) as v_list then
@@ -319,11 +319,11 @@ feature -- HTTP Methods
create s.make_empty
f.append_to_html (l_page.wsf_theme, s)
l_page.set_main_content (s)
l_page.execute
else
-- Responding with `main_content_html (l_page)'.
create {NOT_FOUND_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
send_not_found (req, res)
end
l_page.execute
end
do_get_vocabularies (req: WSF_REQUEST; res: WSF_RESPONSE)

View File

@@ -99,11 +99,11 @@ feature -- HTTP Methods
end
s.append ("</ul>")
l_page.set_main_content (s)
l_page.execute
else
-- Responding with `main_content_html (l_page)'.
create {NOT_FOUND_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
send_not_found (req, res)
end
l_page.execute
else
-- Responding with `main_content_html (l_page)'.
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)

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
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
@@ -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,12 +99,7 @@ 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
end
end
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
@@ -111,6 +109,58 @@ feature -- Files
f_src.close
Result := True -- Succeed!
end
else
Result := False -- No parent directory!
end
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
rescue
retried := True
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

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,10 +109,15 @@ 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.set_title (r.translation ("CMS Installation ...", Void))
r.execute
end
end
note
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"

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

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="all" uuid="1172C52C-6979-4293-8F01-80FADA5A2B69">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="all" uuid="C8FBADFC-FC8D-43F4-AA09-55304BC9342A">
<description>Integration project including many lib</description>
<target name="all">
<root all_classes="true"/>