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
@@ -183,10 +183,10 @@ feature {NONE} -- Implementation: routes
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api) create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.add_block (login_block ("login", "Wrong username", r), "content") r.add_block (login_block ("login", "Wrong username", r), "content")
end end
r.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_access_denied (Void, req, res)
end end
r.execute
end end
feature -- Hooks configuration feature -- Hooks configuration
@@ -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;
}
}
+38
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}
+7 -3
View File
@@ -17,15 +17,19 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_name: READABLE_STRING_32) make (a_name: READABLE_STRING_GENERAL)
-- Create an object with name `a_name'. -- Create an object with name `a_name'.
require require
a_name_not_empty: not a_name.is_whitespace a_name_not_empty: not a_name.is_whitespace
do 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 initialize
ensure ensure
name_set: name = a_name name_set: name.same_string_general (a_name)
status_not_active: status = not_active status_not_active: status = not_active
end end
+4 -3
View File
@@ -3,17 +3,18 @@
<target name="recaptcha"> <target name="recaptcha">
<root all_classes="true"/> <root all_classes="true"/>
<file_rule> <file_rule>
<exclude>/.git$</exclude> <exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude> <exclude>/CVS$</exclude>
<exclude>/.svn$</exclude> <exclude>/\.svn$</exclude>
</file_rule> </file_rule>
<option warning="true" void_safety="all"> <option warning="true" void_safety="all">
</option> </option>
<setting name="concurrency" value="scoop"/> <setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <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="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"/> <cluster name="recaptcha" location=".\src\" recursive="true"/>
</target> </target>
</system> </system>
+5 -6
View File
@@ -3,19 +3,18 @@
<target name="recaptcha"> <target name="recaptcha">
<root all_classes="true"/> <root all_classes="true"/>
<file_rule> <file_rule>
<exclude>/.git$</exclude> <exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude> <exclude>/CVS$</exclude>
<exclude>/.svn$</exclude> <exclude>/\.svn$</exclude>
</file_rule> </file_rule>
<option warning="true" void_safety="none"> <option warning="true" void_safety="none">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option> </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" 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="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 name="recaptcha" location=".\src\" recursive="true">
</cluster> </cluster>
</target> </target>
+9 -11
View File
@@ -98,26 +98,24 @@ feature {NONE} -- REST API
get: detachable RESPONSE get: detachable RESPONSE
-- Reading Data -- Reading Data
local
l_request: REQUEST
do do
create l_request.make ("GET", new_uri) Result := (create {REQUEST}.make ("GET", new_uri)).execute
Result := l_request.execute
end end
feature {NONE} -- Implementation feature {NONE} -- Implementation
new_uri: STRING_8 new_uri: STRING_8
-- new uri (BaseUri?secret=secret_value&response=response_value[&remoteip=remoteip_value] -- new uri (BaseUri?secret=secret_value&response=response_value[&remoteip=remoteip_value]
local
l_uri: URI
do do
create Result.make_from_string (base_uri) create l_uri.make_from_string (base_uri)
Result.append ("?secret=") l_uri.add_query_parameter ("secret", secret)
Result.append (secret) l_uri.add_query_parameter ("response", response)
Result.append ("&response=")
Result.append (response)
if attached remoteip as l_remoteip then if attached remoteip as l_remoteip then
Result.append ("&remoteip=" + l_remoteip) l_uri.add_query_parameter ("remoteip", l_remoteip)
end end
Result := l_uri.string
end end
put_error (a_code: READABLE_STRING_GENERAL) put_error (a_code: READABLE_STRING_GENERAL)
@@ -134,7 +132,7 @@ feature {NONE} -- Implementation
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -51,7 +51,7 @@ feature {NONE} -- Router/administration
l_roles_handler: CMS_ADMIN_ROLES_HANDLER l_roles_handler: CMS_ADMIN_ROLES_HANDLER
l_formats_handler: CMS_ADMIN_FORMATS_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_role_handler: CMS_ROLE_HANDLER
l_admin_logs_handler: CMS_LOGS_HANDLER l_admin_logs_handler: CMS_LOGS_HANDLER
@@ -47,10 +47,10 @@ feature -- Execution
create s.make_empty create s.make_empty
f.append_to_html (l_response.wsf_theme, s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_custom_access_denied (Void, <<"admin cache">>, req, res)
end end
l_response.execute
end end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE) do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -77,10 +77,10 @@ feature -- Execution
create s.make_empty create s.make_empty
f.append_to_html (l_response.wsf_theme, s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_custom_access_denied (Void, <<"admin cache">>, req, res)
end end
l_response.execute
end end
feature -- Widget feature -- Widget
@@ -47,10 +47,10 @@ feature -- Execution
create s.make_empty create s.make_empty
f.append_to_html (l_response.wsf_theme, s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_access_denied (req, res)
end end
l_response.execute
end end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE) do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -92,10 +92,10 @@ feature -- Execution
create s.make_empty create s.make_empty
f.append_to_html (l_response.wsf_theme, s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_access_denied (req, res)
end end
l_response.execute
end end
feature -- Widget feature -- Widget
+5 -7
View File
@@ -3,7 +3,7 @@ note
handler for CMS admin in the CMS interface. handler for CMS admin in the CMS interface.
TODO: implement REST API. TODO: implement REST API.
]" ]"
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -64,12 +64,11 @@ feature -- HTTP Methods
local local
r: CMS_RESPONSE r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
if r.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
create {CMS_ADMIN_RESPONSE} r.make (req, res, api) create {CMS_ADMIN_RESPONSE} r.make (req, res, api)
r.execute r.execute
else else
r.execute send_access_denied (req, res)
end end
end end
@@ -77,12 +76,11 @@ feature -- HTTP Methods
local local
r: CMS_RESPONSE r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
if r.has_permission ("manage " + {CMS_ADMIN_MODULE}.name) then
create {CMS_ADMIN_RESPONSE} r.make (req, res, api) create {CMS_ADMIN_RESPONSE} r.make (req, res, api)
r.execute r.execute
else else
r.execute send_access_denied (req, res)
end end
end end
@@ -47,10 +47,10 @@ feature -- Execution
create s.make_empty create s.make_empty
f.append_to_html (l_response.wsf_theme, s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_access_denied (req, res)
end end
l_response.execute
end end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE) do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -99,11 +99,10 @@ feature -- Execution
create s.make_empty create s.make_empty
f.append_to_html (l_response.wsf_theme, s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_access_denied (req, res)
end end
l_response.execute
end end
feature -- Widget feature -- Widget
@@ -60,8 +60,7 @@ feature -- Execution
l_denied := True l_denied := True
end end
if l_denied then if l_denied then
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) send_custom_access_denied ("You do not have permission to access CMS module uninstallation procedure!", Void, req, res)
r.set_main_content ("You do not have permission to access CMS module uninstallation procedure!")
else else
create s.make_empty create s.make_empty
across across
@@ -82,8 +81,8 @@ feature -- Execution
end end
s.append (r.link ("Back to modules management", r.location, Void)) s.append (r.link ("Back to modules management", r.location, Void))
r.set_main_content (s) r.set_main_content (s)
r.execute
end end
r.execute
else else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create s.make_empty create s.make_empty
@@ -119,8 +118,7 @@ feature -- Execution
l_denied := True l_denied := True
end end
if l_denied then if l_denied then
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) send_custom_access_denied ("You do not have permission to access CMS module installation procedure!", Void, req, res)
r.set_main_content ("You do not have permission to access CMS module installation procedure!")
else else
f := modules_to_install_collection_web_form (r) f := modules_to_install_collection_web_form (r)
f.submit_actions.extend (agent on_installation_submit) f.submit_actions.extend (agent on_installation_submit)
@@ -138,8 +136,8 @@ feature -- Execution
r.add_notice_message ("Operation on module(s) succeeded.") r.add_notice_message ("Operation on module(s) succeeded.")
r.set_redirection (r.location) r.set_redirection (r.location)
end end
r.execute
end end
r.execute
elseif l_op.same_string ("Update status") then elseif l_op.same_string ("Update status") then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if api.has_permission ("admin module") then if api.has_permission ("admin module") then
@@ -159,15 +157,12 @@ feature -- Execution
r.add_notice_message ("Operation on module(s) succeeded.") r.add_notice_message ("Operation on module(s) succeeded.")
r.set_redirection (r.location) r.set_redirection (r.location)
end end
r.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) send_custom_access_denied ("You do not have permission to administrate CMS modules!", Void, req, res)
r.set_main_content ("You do not have permission to administrate CMS modules!")
end end
r.execute
else else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api) send_bad_request (req, res)
r.execute
end end
else else
do_get (req, res) do_get (req, res)
@@ -81,10 +81,10 @@ feature -- Execution
s.append ("</ul>") s.append ("</ul>")
end end
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_access_denied (req, res)
end end
l_response.execute
end end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE) 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 (l_response.location)
l_response.set_redirection_delay (3) l_response.set_redirection_delay (3)
l_response.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) send_access_denied (req, res)
l_response.set_redirection (l_response.location) -- CHECK: set redirection?
end end
l_response.execute
end end
end end
@@ -152,8 +152,8 @@ feature -- View/edit Format
i := i + 1 i := i + 1
l_name := f_ic.item.name l_name := f_ic.item.name
l_all_filters.force (f_ic.item, l_name) l_all_filters.force (f_ic.item, l_name)
create cb.make_with_value ("filters[" + l_name + "]", l_name) create cb.make_with_value ("filters[" + l_name + "]", l_name.to_string_32)
cb.set_title (f_ic.item.title) cb.set_title (f_ic.item.title.to_string_32)
cb.set_checked (True) cb.set_checked (True)
create hf.make_with_text ("filter_weight[" + l_name + "]", i.out) 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 l_name := f_ic.item.name
if l_all_filters.has (l_name) then if l_all_filters.has (l_name) then
else else
create cb.make_with_value ("filters[" + l_name + "]", l_name) create cb.make_with_value ("filters[" + l_name + "]", l_name.to_string_32)
cb.set_title (f_ic.item.title) cb.set_title (f_ic.item.title.to_string_32)
create ftb_row.make (2) create ftb_row.make (2)
ftb.add_row (ftb_row) ftb.add_row (ftb_row)
ftb_row.add_widget (cb) ftb_row.add_widget (cb)
@@ -195,8 +195,8 @@ feature -- View/edit Format
api.content_types as ct_ic api.content_types as ct_ic
loop loop
l_name := ct_ic.item.name l_name := ct_ic.item.name
create cb.make_with_value ("content_types[]", l_name) create cb.make_with_value ("content_types[]", l_name.to_string_32)
cb.set_title (l_name) cb.set_title (l_name.to_string_32)
if f /= Void and then ct_ic.item.has_format (f.name) then if f /= Void and then ct_ic.item.has_format (f.name) then
cb.set_checked (True) cb.set_checked (True)
end end
@@ -63,7 +63,7 @@ feature -- HTTP Methods
l_logs: LIST [CMS_LOG] l_logs: LIST [CMS_LOG]
l_log: CMS_LOG l_log: CMS_LOG
r: CMS_RESPONSE r: CMS_RESPONSE
l_cat: detachable READABLE_STRING_8 l_cat: detachable READABLE_STRING_32
l_lower: INTEGER l_lower: INTEGER
l_count: INTEGER l_count: INTEGER
b: STRING b: STRING
@@ -104,11 +104,10 @@ feature -- HTTP Methods
r.set_main_content (b) r.set_main_content (b)
r.set_page_title ("Logs ...") r.set_page_title ("Logs ...")
r.set_title ("Logs") r.set_title ("Logs")
r.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) send_access_denied (req, res)
end end
r.execute
end end
end end
@@ -348,9 +348,9 @@ feature -- Form
fs.extend (lab) fs.extend (lab)
string_sorter.sort (l_permissions) string_sorter.sort (l_permissions)
across l_permissions as ic loop 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_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) fs.extend (cb)
end end
end end
@@ -389,7 +389,7 @@ feature -- Form
update_role (a_form_data: WSF_FORM_DATA; a_role: CMS_USER_ROLE) 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'. -- Update node `a_node' with form_data `a_form_data' for the given content type `a_content_type'.
local local
l_perm: READABLE_STRING_8 l_perm: READABLE_STRING_GENERAL
do do
if attached a_form_data.string_item ("op") as f_op then if attached a_form_data.string_item ("op") as f_op then
if f_op.is_case_insensitive_equal_general ("Update role") then if f_op.is_case_insensitive_equal_general ("Update role") then
@@ -400,16 +400,16 @@ feature -- Form
then then
if attached {WSF_STRING} a_form_data.item ("cms_permissions") as u_role then if attached {WSF_STRING} a_form_data.item ("cms_permissions") as u_role then
a_role.permissions.wipe_out 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 elseif attached {WSF_MULTIPLE_STRING} a_form_data.item ("cms_permissions") as u_permissions then
a_role.permissions.wipe_out a_role.permissions.wipe_out
-- Enable checked permissions. -- Enable checked permissions.
across across
u_permissions as ic u_permissions as ic
loop loop
l_perm := ic.item.value.as_string_8 l_perm := ic.item.value
if not l_perm.is_whitespace then 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
end end
else else
@@ -421,9 +421,9 @@ feature -- Form
l_cms_perms.values as ic l_cms_perms.values as ic
loop loop
if attached {WSF_STRING} ic.item as p then 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 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 end
end end
@@ -81,10 +81,8 @@ feature -- HTTP Methods
l_uid: INTEGER_64 l_uid: INTEGER_64
edit_response: CMS_ROLE_FORM_RESPONSE edit_response: CMS_ROLE_FORM_RESPONSE
view_response: CMS_ROLE_VIEW_RESPONSE view_response: CMS_ROLE_VIEW_RESPONSE
r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("admin roles") then
if r.has_permission ("admin roles") then
if req.percent_encoded_path_info.ends_with_general ("/edit") 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 check valid_url: req.percent_encoded_path_info.starts_with_general (api.administration_path ("/role/")) end
create edit_response.make (req, res, api) create edit_response.make (req, res, api)
@@ -111,18 +109,15 @@ feature -- HTTP Methods
end end
end end
else else
r.execute send_access_denied (req, res)
end end
end end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE) do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
local local
edit_response: CMS_ROLE_FORM_RESPONSE edit_response: CMS_ROLE_FORM_RESPONSE
r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("admin roles") then
if r.has_permission ("admin roles") then
if req.percent_encoded_path_info.ends_with_general ("/edit") then if req.percent_encoded_path_info.ends_with_general ("/edit") then
create edit_response.make (req, res, api) create edit_response.make (req, res, api)
edit_response.execute edit_response.execute
@@ -138,7 +133,7 @@ feature -- HTTP Methods
edit_response.execute edit_response.execute
end end
else else
r.execute send_access_denied (req, res)
end end
end end
@@ -71,7 +71,7 @@ feature -- Execution
s.append ("<div class=%"info%"> ") s.append ("<div class=%"info%"> ")
s.append ("<h4>Role Information</h4>") s.append ("<h4>Role Information</h4>")
s.append ("<p>Role:") s.append ("<p>Role:")
s.append (a_role.name) s.append (html_encoded (a_role.name))
s.append ("</p>") s.append ("</p>")
s.append ("<h4>Permissions:</h4>") s.append ("<h4>Permissions:</h4>")
@@ -1,10 +1,10 @@
note note
description: "Summary description for {CMS_USER_FORM_RESPONSE}." description: "Summary description for {CMS_ADMIN_USER_FORM_RESPONSE}."
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
class class
CMS_USER_FORM_RESPONSE CMS_ADMIN_USER_FORM_RESPONSE
inherit inherit
CMS_RESPONSE CMS_RESPONSE
@@ -324,10 +324,10 @@ feature -- Form
create fs.make create fs.make
fs.set_legend ("Basic User Account Information") fs.set_legend ("Basic User Account Information")
fs.extend_html_text ("<div><string><label>User name </label></strong><br></div>") 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 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 else
create fe.make_with_text ("email", "") create fe.make_with_text ("email", "")
end end
@@ -477,7 +477,7 @@ feature -- Form
api.user_api.user_by_email (l_email) = Void api.user_api.user_by_email (l_email) = Void
then then
-- Valid email -- Valid email
a_user.set_email (l_email) a_user.set_email (api.utf_8_encoded (l_email))
else else
if attached l_user.email as u_email and then not u_email.is_case_insensitive_equal_general (l_email) then 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!") a_form_data.report_invalid_field ("email", "Email already exist!")
@@ -1,12 +1,12 @@
note note
description: "[ description: "[
Handler for a CMS user in the CMS interface Administration handler for a CMS user in the CMS interface
]" ]"
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
class class
CMS_USER_HANDLER CMS_ADMIN_USER_HANDLER
inherit inherit
CMS_HANDLER CMS_HANDLER
@@ -79,12 +79,10 @@ feature -- HTTP Methods
local local
l_user: detachable CMS_USER l_user: detachable CMS_USER
l_uid: INTEGER_64 l_uid: INTEGER_64
edit_response: CMS_USER_FORM_RESPONSE edit_response: CMS_ADMIN_USER_FORM_RESPONSE
view_response: CMS_USER_VIEW_RESPONSE view_response: CMS_ADMIN_USER_VIEW_RESPONSE
r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("admin users") then
if r.has_permission ("admin users") then
if req.percent_encoded_path_info.ends_with_general ("/edit") 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 check valid_url: req.percent_encoded_path_info.starts_with_general (api.administration_path ("/user/")) end
create edit_response.make (req, res, api) create edit_response.make (req, res, api)
@@ -111,18 +109,16 @@ feature -- HTTP Methods
end end
end end
else else
r.execute send_access_denied (req, res)
end end
end end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE) do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
local local
edit_response: CMS_USER_FORM_RESPONSE edit_response: CMS_ADMIN_USER_FORM_RESPONSE
r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("admin users") then
if r.has_permission ("admin users") then
if req.percent_encoded_path_info.ends_with_general ("/edit") then if req.percent_encoded_path_info.ends_with_general ("/edit") then
create edit_response.make (req, res, api) create edit_response.make (req, res, api)
edit_response.execute edit_response.execute
@@ -138,7 +134,7 @@ feature -- HTTP Methods
edit_response.execute edit_response.execute
end end
else else
r.execute send_access_denied (req, res)
end end
end end
@@ -190,7 +186,7 @@ feature {NONE} -- New User
create_new_user (req: WSF_REQUEST; res: WSF_RESPONSE) create_new_user (req: WSF_REQUEST; res: WSF_RESPONSE)
local local
edit_response: CMS_USER_FORM_RESPONSE edit_response: CMS_ADMIN_USER_FORM_RESPONSE
do do
if req.percent_encoded_path_info.starts_with (api.administration_path ("/add/user")) then if req.percent_encoded_path_info.starts_with (api.administration_path ("/add/user")) then
create edit_response.make (req, res, api) create edit_response.make (req, res, api)
@@ -1,10 +1,10 @@
note note
description: "Summary description for {CMS_USER_VIEW_RESPONSE}." description: "Summary description for {CMS_ADMIN_USER_VIEW_RESPONSE}."
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
class class
CMS_USER_VIEW_RESPONSE CMS_ADMIN_USER_VIEW_RESPONSE
inherit inherit
CMS_RESPONSE CMS_RESPONSE
@@ -27,7 +27,6 @@ feature -- Query
end end
end end
feature -- Execution feature -- Execution
process process
@@ -73,8 +73,7 @@ feature -- HTTP Methods
-- get them from the configuration file and load them into -- get them from the configuration file and load them into
-- the setup class. -- the setup class.
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api) if api.has_permission ("admin users") then
if l_response.has_permission ("admin users") then
user_api := api.user_api user_api := api.user_api
l_count := user_api.users_count l_count := user_api.users_count
@@ -157,7 +156,7 @@ feature -- HTTP Methods
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute l_response.execute
else else
l_response.execute send_access_denied (req, res)
end end
end end
end end
@@ -81,7 +81,7 @@ feature -- Basic Operations / Internal
feature -- Basic Operations / Contact 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. -- Send new user register to webmaster to confirm or reject itt.
local local
l_message: STRING l_message: STRING
@@ -95,7 +95,7 @@ feature -- Basic Operations / Contact
else else
l_message.replace_substring_all ("$email", "unknown email") l_message.replace_substring_all ("$email", "unknown email")
end 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 ("$activation_url", a_url_activate)
l_message.replace_substring_all ("$rejection_url", a_url_reject) 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) send_message (contact_email_address, contact_email_address, parameters.contact_subject_account_evaluation, l_message)
@@ -13,7 +13,6 @@ feature {NONE} -- Initialization
make (a_cms_api: CMS_API) make (a_cms_api: CMS_API)
local local
utf: UTF_CONVERTER
s: detachable READABLE_STRING_32 s: detachable READABLE_STRING_32
l_utf8_site_name: IMMUTABLE_STRING_8 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 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 if attached a_cms_api.module_configuration_by_name ({CMS_AUTHENTICATION_MODULE}.name, Void) as cfg then
s := cfg.text_item ("email") s := cfg.text_item ("email")
if s /= Void then 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 end
s := cfg.text_item ("subject_register") s := cfg.text_item ("subject_register")
if s /= Void then 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 end
s := cfg.text_item ("subject_activate") s := cfg.text_item ("subject_activate")
if s /= Void then 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 end
s := cfg.text_item ("subject_password") s := cfg.text_item ("subject_password")
if s /= Void then 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 end
s := cfg.text_item ("subject_oauth") s := cfg.text_item ("subject_oauth")
if s /= Void then 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
end end
if l_contact_email = Void then if l_contact_email = Void then
+18 -26
View File
@@ -65,6 +65,7 @@ feature -- Access
Result.force ("account reject") Result.force ("account reject")
Result.force ("account reactivate") Result.force ("account reactivate")
Result.force ("change own username") Result.force ("change own username")
Result.force ("view user")
end end
feature {CMS_EXECUTION} -- Administration 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/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/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 ("/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 end
feature -- Hooks configuration feature -- Hooks configuration
@@ -382,7 +385,7 @@ feature -- Handler
l_exist := True l_exist := True
end end
if attached recaptcha_secret_key (api) as l_recaptcha_key then 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 l_captcha_passed := True
else else
--| Bad or missing captcha --| Bad or missing captcha
@@ -428,15 +431,13 @@ feature -- Handler
r.set_status_code ({HTTP_CONSTANTS}.bad_request) r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end end
else else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_bad_request ("There were issue with your application, invalid or missing values.", req, res)
r.set_main_content ("There were issue with your application, invalid or missing values.")
end end
end end
r.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_permissions_access_denied ("You can also contact the webmaster to ask for an account.", Void, req, res)
r.set_main_content ("You can also contact the webmaster to ask for an account.")
end end
r.execute
end end
handle_activation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_activation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -500,8 +501,7 @@ feature -- Handler
l_ir.execute l_ir.execute
end end
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_access_denied (Void, req, res)
r.execute
end end
end end
@@ -536,8 +536,7 @@ feature -- Handler
l_ir.execute l_ir.execute
end end
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_access_denied (Void, req, res)
r.execute
end end
end end
@@ -551,8 +550,8 @@ feature -- Handler
l_url_reject: STRING l_url_reject: STRING
l_email: READABLE_STRING_8 l_email: READABLE_STRING_8
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("account reactivate") then
if r.has_permission ("account reactivate") then create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if req.is_post_request_method then if req.is_post_request_method then
if attached {WSF_STRING} req.form_parameter ("email") as p_email then if attached {WSF_STRING} req.form_parameter ("email") as p_email then
if p_email.value.is_valid_as_string_8 then if p_email.value.is_valid_as_string_8 then
@@ -587,11 +586,10 @@ feature -- Handler
end end
end end
end end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute r.execute
else
api.response_api.send_access_denied (Void, req, res)
end end
r.execute
end end
handle_new_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) 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 l_fieldname := p_field.url_encoded_value
end end
if l_fieldname = Void then 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 else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
@@ -814,8 +812,8 @@ feature -- Handler
end end
r.set_main_content (b) r.set_main_content (b)
end end
r.execute
end end
r.execute
end end
block_list: ITERABLE [like {CMS_BLOCK}.name] block_list: ITERABLE [like {CMS_BLOCK}.name]
@@ -1118,36 +1116,30 @@ feature -- Access: configuration
form_registration_application_description (api: CMS_API): detachable READABLE_STRING_8 form_registration_application_description (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key. -- Get recaptcha security key.
local
utf: UTF_CONVERTER
do do
if attached api.module_configuration (Current, Void) as cfg then 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 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 end
end end
recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8 recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key. -- Get recaptcha security key.
local
utf: UTF_CONVERTER
do do
if attached api.module_configuration (Current, Void) as cfg then 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 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 end
end end
recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8 recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key. -- Get recaptcha security key.
local
utf: UTF_CONVERTER
do do
if attached api.module_configuration (Current, Void) as cfg then 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 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 end
end end
@@ -54,9 +54,8 @@ feature -- Request handling
-- get them from the configuration file and load them into -- get them from the configuration file and load them into
-- the setup class. -- the setup class.
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
if if
l_response.has_permission ("admin registration") api.has_permission ("admin registration")
then then
l_user_api := api.user_api l_user_api := api.user_api
@@ -127,7 +126,7 @@ feature -- Request handling
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute l_response.execute
else else
l_response.execute api.response_api.send_access_denied (Void, req, res)
end end
end end
+103
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
+103
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
+2 -6
View File
@@ -37,8 +37,6 @@ feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE) do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- <Precursor> -- <Precursor>
local
l_error: NOT_FOUND_ERROR_CMS_RESPONSE
do do
check user_void: user = Void end check user_void: user = Void end
if attached user_from_request (req) as l_user then if attached user_from_request (req) as l_user then
@@ -47,13 +45,11 @@ feature -- HTTP Methods
Precursor (req, res) Precursor (req, res)
else else
-- Throw a bad request error because the user is not valid -- 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 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 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 end
l_error.execute
end end
user := Void user := Void
end end
+2 -6
View File
@@ -123,30 +123,26 @@ feature -- Recaptcha
recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8 recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key. -- Get recaptcha security key.
local
utf: UTF_CONVERTER
do do
if attached api.module_configuration (Current, Void) as cfg then if attached api.module_configuration (Current, Void) as cfg then
if if
attached cfg.text_item ("recaptcha.secret_key") as l_recaptcha_key and then attached cfg.text_item ("recaptcha.secret_key") as l_recaptcha_key and then
not l_recaptcha_key.is_empty not l_recaptcha_key.is_empty
then 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 end
end end
recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8 recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key. -- Get recaptcha security key.
local
utf: UTF_CONVERTER
do do
if attached api.module_configuration (Current, Void) as cfg then if attached api.module_configuration (Current, Void) as cfg then
if if
attached cfg.text_item ("recaptcha.site_key") as l_recaptcha_key and then attached cfg.text_item ("recaptcha.site_key") as l_recaptcha_key and then
not l_recaptcha_key.is_empty not l_recaptcha_key.is_empty
then 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 end
end end
@@ -13,13 +13,12 @@ feature {NONE} -- Initialization
make (a_cms_api: CMS_API; a_contact_module: CMS_CONTACT_MODULE) make (a_cms_api: CMS_API; a_contact_module: CMS_CONTACT_MODULE)
local local
utf: UTF_CONVERTER
l_site_name: READABLE_STRING_8 l_site_name: READABLE_STRING_8
s: detachable READABLE_STRING_32 s: detachable READABLE_STRING_32
l_contact_email, l_contact_subject: detachable READABLE_STRING_8 l_contact_email, l_contact_subject: detachable READABLE_STRING_8
do do
-- Use global smtp setting if any, otherwise "localhost" -- 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 admin_email := a_cms_api.setup.site_email
if not admin_email.has ('<') then 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 if attached {CONFIG_READER} a_cms_api.module_configuration (a_contact_module, Void) as cfg then
s := cfg.text_item ("email") s := cfg.text_item ("email")
if s /= Void then 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 end
s := cfg.text_item ("subject") s := cfg.text_item ("subject")
if s /= Void then 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
end end
if l_contact_email /= Void then if l_contact_email /= Void then
@@ -25,7 +25,6 @@ feature -- Change
save_contact_message (m: CONTACT_MESSAGE) save_contact_message (m: CONTACT_MESSAGE)
local local
s: STRING s: STRING
utf: UTF_CONVERTER
now: DATE_TIME now: DATE_TIME
do do
error_handler.reset error_handler.reset
@@ -38,7 +37,7 @@ feature -- Change
s.append (m.date.out) s.append (m.date.out)
s.append_character ('%N') s.append_character ('%N')
s.append ("name=") 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') s.append_character ('%N')
if attached m.email as l_email then if attached m.email as l_email then
@@ -47,7 +46,7 @@ feature -- Change
s.append_character ('%N') s.append_character ('%N')
end end
s.append ("message=%N") 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') s.append_character ('%N')
save_to_file (s, date_to_yyyymmdd_hhmmss_string (now)) save_to_file (s, date_to_yyyymmdd_hhmmss_string (now))
@@ -253,11 +253,19 @@ feature {NONE} -- Implementation
end end
replace_substring_all (s: STRING_GENERAL; a_old: READABLE_STRING_8; a_new: STRING_GENERAL) replace_substring_all (s: STRING_GENERAL; a_old: READABLE_STRING_8; a_new: STRING_GENERAL)
local
utf: UTF_CONVERTER
do do
if attached {STRING_8} s as s8 then if attached {STRING_8} s as s8 then
s8.replace_substring_all (a_old, a_new.to_string_8) 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 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
end end
@@ -35,7 +35,6 @@ feature -- Access
l_feed_id: READABLE_STRING_32 l_feed_id: READABLE_STRING_32
l_title: detachable READABLE_STRING_GENERAL l_title: detachable READABLE_STRING_GENERAL
l_locations: detachable STRING_TABLE [READABLE_STRING_8] l_locations: detachable STRING_TABLE [READABLE_STRING_8]
utf: UTF_CONVERTER
l_table: like internal_aggregations l_table: like internal_aggregations
do do
l_table := internal_aggregations l_table := internal_aggregations
@@ -56,20 +55,20 @@ feature -- Access
across across
l_location_list as loc_ic l_location_list as loc_ic
loop 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
end end
if attached cfg.text_table_item ({STRING_32} "feeds." + l_feed_id + ".locations") as l_location_table then if attached cfg.text_table_item ({STRING_32} "feeds." + l_feed_id + ".locations") as l_location_table then
across across
l_location_table as loc_tb_ic l_location_table as loc_tb_ic
loop 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
end end
if if
attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".location") as l_location attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".location") as l_location
then 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 end
if l_locations /= Void and then not l_locations.is_empty then if l_locations /= Void and then not l_locations.is_empty then
l_title := cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".title") l_title := cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".title")
@@ -93,7 +92,7 @@ feature -- Access
across across
l_locations as loc_ic l_locations as loc_ic
loop 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 end
Result.force (agg, l_feed_id) Result.force (agg, l_feed_id)
if attached cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + ".categories") as l_cats then if attached cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + ".categories") as l_cats then
@@ -98,8 +98,7 @@ feature -- Handle
m.header.put_content_type_text_html m.header.put_content_type_text_html
res.send (m) res.send (m)
else else
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, a_api) a_api.response_api.send_not_found (Void, req, res)
r.execute
end end
else else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api)
@@ -143,8 +142,7 @@ feature -- Handle
r.execute r.execute
end end
else else
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, a_api) a_api.response_api.send_not_found (Void, req, res)
r.execute
end end
else else
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api) 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. -- List of block names, managed by current object.
local local
res: ARRAYED_LIST [like {CMS_BLOCK}.name] res: ARRAYED_LIST [like {CMS_BLOCK}.name]
utf_conv: UTF_CONVERTER
do do
if if
attached feed_aggregator_api as l_feed_api and then attached feed_aggregator_api as l_feed_api and then
@@ -209,7 +206,7 @@ feature -- Hook
across across
l_aggs as ic l_aggs as ic
loop 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 end
else else
create res.make (0) create res.make (0)
+9 -10
View File
@@ -140,8 +140,8 @@ feature -- Handler
do do
check req.is_get_request_method end check req.is_get_request_method end
if not api.has_permission (browse_files_permission) then if not api.has_permission (browse_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, <<browse_files_permission>>)
r.add_error_message ("You are not allowed to browse CMS files!") r.add_error_message ("You are not allowed to browse files!")
elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) 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 action=%"" + r.url (uploads_location, Void) + "%" class=%"dropzone%">")
body.append ("</form>%N") 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 end
body.append ("</div>") body.append ("</div>")
end end
@@ -284,15 +284,15 @@ feature -- Handler
if req.is_get_head_request_method then if req.is_get_head_request_method then
-- Build the response. -- Build the response.
if r.has_permission (browse_files_permission) then 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) append_uploaded_file_album_to (req, api, body)
else else
r.add_warning_message ("You are not allowed to browse files!") r.add_warning_message ("You are not allowed to browse files!")
end end
end end
r.set_main_content (body) r.set_main_content (body)
r.execute
elseif req.is_post_request_method then elseif req.is_post_request_method then
if api.has_permission (upload_files_permission) then if api.has_permission (upload_files_permission) then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
@@ -305,14 +305,13 @@ feature -- Handler
r.set_redirection (r.url (uploads_location, Void)) r.set_redirection (r.url (uploads_location, Void))
end end
r.set_main_content (body) r.set_main_content (body)
r.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_permissions_access_denied ("You are not allowed to upload file!", <<upload_files_permission>>, req, res)
r.set_main_content ("You are not allowed to upload file!")
end end
else else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_bad_request (Void, req, res)
end end
r.execute
end end
process_uploaded_files (req: WSF_REQUEST; api: CMS_API; a_output: STRING) process_uploaded_files (req: WSF_REQUEST; api: CMS_API; a_output: STRING)
@@ -472,7 +471,7 @@ feature -- Handler
do do
if attached files_api as l_files_api then if attached files_api as l_files_api then
if not api.has_permission (admin_files_permission) 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!") r.add_error_message ("You are not allowed to remove file!")
elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then elseif attached {WSF_STRING} req.path_parameter ("filename") as p_filename then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
+7 -5
View File
@@ -83,14 +83,16 @@ feature -- Element change
-- sets `a_number' after the name. This is done when the file was already uploaded -- sets `a_number' after the name. This is done when the file was already uploaded
local local
position: INTEGER_32 position: INTEGER_32
new_name: STRING_8 new_name: STRING_32
l_uploaded_file_string_representation: READABLE_STRING_32
do 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 create new_name.make_empty
new_name := uploaded_file.string_representation.head (position-1) new_name := l_uploaded_file_string_representation.head (position-1)
new_name.append ("_(" + a_number.out + ")") new_name.append_string_general ("_(" + a_number.out + ")")
new_name.append (uploaded_file.string_representation.substring (position, uploaded_file.string_representation.count)) new_name.append (l_uploaded_file_string_representation.substring (position, l_uploaded_file_string_representation.count))
location := uploads_directory.extended (new_name) location := uploads_directory.extended (new_name)
end end
@@ -57,15 +57,13 @@ feature -- GCSE Keys
gcse_cx_key (api: CMS_API): detachable READABLE_STRING_8 gcse_cx_key (api: CMS_API): detachable READABLE_STRING_8
-- Get google custom search engine id. -- Get google custom search engine id.
local
utf: UTF_CONVERTER
do do
if attached api.module_configuration (Current, Void) as cfg then if attached api.module_configuration (Current, Void) as cfg then
if if
attached cfg.text_item ("gcse.search_engine_id") as l_gcse_cx_key and then attached cfg.text_item ("gcse.search_engine_id") as l_gcse_cx_key and then
not l_gcse_cx_key.is_empty not l_gcse_cx_key.is_empty
then 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 end
end end
+4 -5
View File
@@ -223,12 +223,12 @@ $(document).ready(function() {
local local
r: CMS_RESPONSE r: CMS_RESPONSE
do 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) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.values.force ("messaging", "messaging") r.values.force ("messaging", "messaging")
r.set_main_content (new_html_messaging_form (r, api)) r.set_main_content (new_html_messaging_form (r, api))
else 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 end
r.execute r.execute
end end
@@ -314,7 +314,7 @@ $(document).ready(function() {
end end
r.set_main_content (s) r.set_main_content (s)
else 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 end
r.execute r.execute
end 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 resolved_template_text (api: CMS_API; a_text: READABLE_STRING_GENERAL; a_target_user: detachable CMS_USER): STRING_8
local local
smt: CMS_SMARTY_TEMPLATE_TEXT smt: CMS_SMARTY_TEMPLATE_TEXT
utf: UTF_CONVERTER
do 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 across
api.builtin_variables as vars_ic api.builtin_variables as vars_ic
loop loop
+1 -1
View File
@@ -372,7 +372,7 @@ feature -- Hooks
loop loop
if if
attached ic.item.typename as l_typename and then 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 then
if ic.item.entity.is_integer then if ic.item.entity.is_integer then
nid := ic.item.entity.to_integer_64 nid := ic.item.entity.to_integer_64
@@ -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.") 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 end
ti.set_text_value (l_uri) ti.set_text_value (l_uri.to_string_32)
ti.set_placeholder (l_auto_path_alias) 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) ti.set_validation_action (agent (fd: WSF_FORM_DATA; ia_response: NODE_RESPONSE; ia_node: detachable CMS_NODE)
do do
if if
@@ -204,7 +204,7 @@ feature -- Forms ...
end end
-- Auto path alias / suggestion -- Auto path alias / suggestion
create thi.make ("auto_path_alias") 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) thi.set_is_readonly (True)
f.insert_before (thi, w) f.insert_before (thi, w)
end end
+5 -1
View File
@@ -241,7 +241,11 @@ feature -- Form
if attached fd.string_item ("content") as l_content then if attached fd.string_item ("content") as l_content then
b.append ("<strong>Content:</strong><div class=%"content%">") b.append ("<strong>Content:</strong><div class=%"content%">")
if l_format /= Void then 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 else
b.append (html_encoded (l_content)) b.append (html_encoded (l_content))
end end
+10 -7
View File
@@ -75,6 +75,14 @@ feature -- Query
end end
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 feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE) do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -148,7 +156,7 @@ feature -- HTTP Methods
attached api.user as l_user and then attached api.user as l_user and then
( node_api.is_author_of_node (l_user, l_node) ( node_api.is_author_of_node (l_user, l_node)
or else ( 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 then
@@ -403,15 +411,10 @@ feature -- Error
send_access_denied_to_unpublished_node (req: WSF_REQUEST; res: WSF_RESPONSE; a_node: CMS_NODE) send_access_denied_to_unpublished_node (req: WSF_REQUEST; res: WSF_RESPONSE; a_node: CMS_NODE)
-- Forbidden response. -- Forbidden response.
local
r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) send_custom_access_denied ("This content is NOT published!", view_unpublished_permissions (a_node), req, res)
r.set_main_content ("This content is NOT published!")
r.execute
end end
feature {NONE} -- Node feature {NONE} -- Node
create_new_node (req: WSF_REQUEST; res: WSF_RESPONSE) create_new_node (req: WSF_REQUEST; res: WSF_RESPONSE)
+1 -2
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.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented<br/>", Void), "highlighted")
l_page.execute l_page.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_page.make (req, res, api) send_custom_access_denied (Void, <<"view trash", "view any trash", "view own trash">>, req, res)
l_page.execute
end end
end end
+1 -1
View File
@@ -79,7 +79,7 @@ feature -- Access: Consumers OAuth20
Result := openid_storage.openid_consumers Result := openid_storage.openid_consumers
end 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. -- Retrieve a consumer by name `a_name', if any.
do do
Result := openid_storage.openid_consumer_by_name (a_name) Result := openid_storage.openid_consumer_by_name (a_name)
+7 -5
View File
@@ -226,7 +226,7 @@ feature -- Hooks
create o.make (req.absolute_script_url ("/account/auth/login-with-openid")) create o.make (req.absolute_script_url ("/account/auth/login-with-openid"))
o.ask_email (True) o.ask_email (True)
o.ask_all_info (False) 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) r.set_redirection (l_url)
else else
s.append (" Failure") s.append (" Failure")
@@ -248,7 +248,7 @@ feature -- Hooks
attached {WSF_STRING} req.cookie (a_openid_api.session_token) as l_cookie_token attached {WSF_STRING} req.cookie (a_openid_api.session_token) as l_cookie_token
then then
-- Logout OAuth -- 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_path ("/")
l_cookie.set_max_age (-1) l_cookie.set_max_age (-1)
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -335,6 +335,7 @@ feature -- Openid Login
b: STRING b: STRING
o: OPENID_CONSUMER o: OPENID_CONSUMER
v: OPENID_CONSUMER_VALIDATION v: OPENID_CONSUMER_VALIDATION
l_email: STRING_8
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty create b.make_empty
@@ -346,8 +347,9 @@ feature -- Openid Login
v.validate v.validate
if v.is_valid then if v.is_valid then
if attached v.identity as l_identity and 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 then
l_email := api.utf_8_encoded (l_email_attrib)
l_user_api := api.user_api l_user_api := api.user_api
if attached l_user_api.user_by_email (l_email) as p_user then if attached l_user_api.user_by_email (l_email) as p_user then
-- User with email exist -- User with email exist
@@ -355,7 +357,7 @@ feature -- Openid Login
-- Update openid entry? -- Update openid entry?
else else
-- create a oauth entry -- 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 end
create l_cookie.make (a_openid_api.session_token, l_identity) create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (a_openid_api.session_max_age) 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) l_roles.force (l_user_api.authenticated_user_role)
-- Create a new user and oauth entry -- 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_email (l_email)
l_user.set_password (new_token) -- generate a random password. l_user.set_password (new_token) -- generate a random password.
l_user.set_roles (l_roles) l_user.set_roles (l_roles)
@@ -37,7 +37,7 @@ feature -- Access: Consumers
deferred deferred
end 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. -- Retrieve a consumer by name `a_name', if any.
deferred deferred
end end
@@ -49,6 +49,6 @@ feature -- Change: User Oauth2
deferred deferred
end end
end end
@@ -39,7 +39,7 @@ feature -- Access: Consumers
create {ARRAYED_LIST[STRING]}Result.make(0) create {ARRAYED_LIST[STRING]}Result.make(0)
end 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> -- <Precursor>
do do
end end
@@ -99,7 +99,7 @@ feature --Access: Consumers
sql_finalize sql_finalize
end 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. -- Retrieve a consumer by name `a_name', if any.
local local
l_parameters: STRING_TABLE [detachable ANY] l_parameters: STRING_TABLE [detachable ANY]
@@ -141,7 +141,7 @@ feature -- Hook
create s.make_empty create s.make_empty
if attached ch.information as l_information then if attached ch.information as l_information then
s.append (l_information) s.append_string_general (l_information)
end end
if attached ch.summary as sum then if attached ch.summary as sum then
if not s.is_empty then if not s.is_empty then
@@ -248,9 +248,9 @@ feature -- Handler
l_size := 25 l_size := 25
end end
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) if api.has_permission ("view recent changes") then
if r.has_permission ("view recent changes") then create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
l_user := r.user l_user := api.user
create l_changes.make (l_size, l_until_date, l_filter_source) create l_changes.make (l_size, l_until_date, l_filter_source)
create l_content.make (1024) create l_content.make (1024)
@@ -406,11 +406,10 @@ feature -- Handler
create htdate.make_from_date_time (l_until_date) create htdate.make_from_date_time (l_until_date)
r.set_title ("Recent changes before " + htdate.string) r.set_title ("Recent changes before " + htdate.string)
end end
r.execute
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_permissions_access_denied (Void, <<"view recent changes">>, req, res)
end end
r.execute
end end
feature -- Hooks configuration feature -- Hooks configuration
+1 -2
View File
@@ -123,8 +123,7 @@ feature -- Handler
mesg.set_payload (l_sitemap_xml) mesg.set_payload (l_sitemap_xml)
res.send (mesg) res.send (mesg)
else else
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_not_found (Void, req, res)
r.execute
end end
end end
end end
+2 -2
View File
@@ -143,11 +143,11 @@ feature -- HTTP Methods
s.append ("No entity found.") s.append ("No entity found.")
end end
l_page.set_main_content (s) l_page.set_main_content (s)
l_page.execute
else else
-- Responding with `main_content_html (l_page)'. -- 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 end
l_page.execute
else else
-- Responding with `main_content_html (l_page)'. -- Responding with `main_content_html (l_page)'.
create {BAD_REQUEST_ERROR_CMS_RESPONSE} l_page.make (req, res, api) create {BAD_REQUEST_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
@@ -277,13 +277,13 @@ feature -- HTTP Methods
l_typename := ic.item.name l_typename := ic.item.name
create w_cb.make_with_value ("typenames[]", api.html_encoded (l_typename)) 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) wtb_row.set_item (create {WSF_WIDGET_TABLE_ITEM}.make_with_content (w_cb), 1)
v := Void v := Void
if if
l_typenames /= Void and then 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 then
w_cb.set_checked (True) w_cb.set_checked (True)
if attached taxonomy_api.vocabularies_for_type (l_typename) as v_list then if attached taxonomy_api.vocabularies_for_type (l_typename) as v_list then
@@ -319,11 +319,11 @@ feature -- HTTP Methods
create s.make_empty create s.make_empty
f.append_to_html (l_page.wsf_theme, s) f.append_to_html (l_page.wsf_theme, s)
l_page.set_main_content (s) l_page.set_main_content (s)
l_page.execute
else else
-- Responding with `main_content_html (l_page)'. -- 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 end
l_page.execute
end end
do_get_vocabularies (req: WSF_REQUEST; res: WSF_RESPONSE) do_get_vocabularies (req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -99,11 +99,11 @@ feature -- HTTP Methods
end end
s.append ("</ul>") s.append ("</ul>")
l_page.set_main_content (s) l_page.set_main_content (s)
l_page.execute
else else
-- Responding with `main_content_html (l_page)'. -- 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 end
l_page.execute
else else
-- Responding with `main_content_html (l_page)'. -- Responding with `main_content_html (l_page)'.
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+14 -8
View File
@@ -87,7 +87,7 @@ feature -- Access
do do
if attached text_item (a_name) as s then if attached text_item (a_name) as s then
if s.is_valid_as_string_8 then if s.is_valid_as_string_8 then
Result := s.as_string_8 Result := s.to_string_8
else else
Result := utf.escaped_utf_32_string_to_utf_8_string_8 (s) Result := utf.escaped_utf_32_string_to_utf_8_string_8 (s)
end end
@@ -101,10 +101,11 @@ feature -- Access
l_chain: NOTIFICATION_CHAIN_MAILER l_chain: NOTIFICATION_CHAIN_MAILER
l_storage_mailer: NOTIFICATION_STORAGE_MAILER l_storage_mailer: NOTIFICATION_STORAGE_MAILER
l_mailer: detachable NOTIFICATION_MAILER l_mailer: detachable NOTIFICATION_MAILER
b: BOOLEAN
do do
if not retried then if not retried then
if attached text_item ("mailer.smtp") as l_smtp then 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.as_string_8_conversion) create {NOTIFICATION_SMTP_MAILER} l_mailer.make (l_smtp.to_string_8)
elseif attached text_item ("mailer.sendmail") as l_sendmail then elseif attached text_item ("mailer.sendmail") as l_sendmail then
create {NOTIFICATION_SENDMAIL_MAILER} l_mailer.make_with_location (l_sendmail) create {NOTIFICATION_SENDMAIL_MAILER} l_mailer.make_with_location (l_sendmail)
end end
@@ -120,19 +121,24 @@ feature -- Access
if f.exists and then f.is_directory then 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)) create {NOTIFICATION_STORAGE_MAILER} l_storage_mailer.make (create {NOTIFICATION_EMAIL_DIRECTORY_STORAGE}.make (f.path))
else else
if not f.exists then if f.exists then
f.create_read_write b := True
f.close 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
create {NOTIFICATION_STORAGE_MAILER} l_storage_mailer.make (create {NOTIFICATION_EMAIL_FILE_STORAGE}.make (f))
end end
end end
if l_mailer /= Void then if l_mailer /= Void then
create l_chain.make (l_mailer) create l_chain.make (l_mailer)
l_chain.set_next (l_storage_mailer) l_chain.set_next (l_storage_mailer)
l_mailer := l_chain l_mailer := l_chain
else elseif l_storage_mailer /= Void then
l_mailer := l_storage_mailer l_mailer := l_storage_mailer
else
create {NOTIFICATION_NULL_MAILER} l_mailer
end end
elseif l_mailer = Void then elseif l_mailer = Void then
create {NOTIFICATION_STORAGE_MAILER} l_mailer.make (create {NOTIFICATION_EMAIL_FILE_STORAGE}.make (io.error)) create {NOTIFICATION_STORAGE_MAILER} l_mailer.make (create {NOTIFICATION_EMAIL_FILE_STORAGE}.make (io.error))
+10 -2
View File
@@ -21,6 +21,14 @@ inherit
feature -- Encoders 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 html_encoded (a_string: READABLE_STRING_GENERAL): STRING_8
-- `a_string' encoded for html output. -- `a_string' encoded for html output.
do do
@@ -36,7 +44,7 @@ feature -- Encoders
Result := "" Result := ""
end end
end end
url_encoded, url_encoded,
percent_encoded (a_string: READABLE_STRING_GENERAL): STRING_8 percent_encoded (a_string: READABLE_STRING_GENERAL): STRING_8
-- `a_string' encoded with percent encoding, mainly used for url. -- `a_string' encoded with percent encoding, mainly used for url.
@@ -45,6 +53,6 @@ feature -- Encoders
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end
+2 -2
View File
@@ -75,7 +75,7 @@ feature -- URL aliases
do do
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
-- Source path for alias `a_alias'. -- Source path for alias `a_alias'.
do do
end end
@@ -136,6 +136,6 @@ feature -- Custom
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end
+2 -2
View File
@@ -42,7 +42,7 @@ feature -- URL aliases
deferred deferred
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
-- Source path for alias `a_alias'. -- Source path for alias `a_alias'.
deferred deferred
end end
@@ -89,6 +89,6 @@ feature -- Misc
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end
@@ -123,7 +123,7 @@ feature -- URL aliases
sql_finalize sql_finalize
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
-- <Precursor> -- <Precursor>
local local
l_parameters: STRING_TABLE [detachable ANY] l_parameters: STRING_TABLE [detachable ANY]
+20 -4
View File
@@ -642,7 +642,7 @@ feature -- Status Report
feature -- Logging 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'. -- 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_category' is set, filter to return only associated logs.
-- If `a_count' <= 0 then, return all logs. -- If `a_count' <= 0 then, return all logs.
@@ -1001,6 +1001,19 @@ feature -- Access: API
Result := l_api Result := l_api
end 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 feature -- Hooks
setup_core_hooks (a_hooks: CMS_HOOK_CORE_MANAGER) setup_core_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
@@ -1014,9 +1027,9 @@ feature -- Hooks
feature -- Path aliases feature -- Path aliases
is_valid_path_alias (a_alias: READABLE_STRING_8): BOOLEAN is_valid_path_alias (a_alias: READABLE_STRING_GENERAL): BOOLEAN
do 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 end
set_path_alias (a_source, a_alias: READABLE_STRING_8; a_keep_previous: BOOLEAN) set_path_alias (a_source, a_alias: READABLE_STRING_8; a_keep_previous: BOOLEAN)
@@ -1076,7 +1089,7 @@ feature -- Path aliases
end end
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'. -- Resolved path for alias `a_alias'.
--| the CMS supports aliases for path, and then this function simply returns --| the CMS supports aliases for path, and then this function simply returns
--| the effective target path/url for this `a_alias'. --| the effective target path/url for this `a_alias'.
@@ -1106,6 +1119,9 @@ feature {NONE}-- Implementation
internal_user_api: detachable like user_api internal_user_api: detachable like user_api
-- Cached value for `user_api`. -- Cached value for `user_api`.
internal_response_api: detachable like response_api
-- Cached value for `response_api`.
feature -- Environment/ theme feature -- Environment/ theme
site_location: PATH site_location: PATH
+11 -21
View File
@@ -196,24 +196,24 @@ feature -- Settings: router
local local
fhdl: WSF_FILE_SYSTEM_HANDLER fhdl: WSF_FILE_SYSTEM_HANDLER
themehdl: CMS_THEME_FILE_SYSTEM_HANDLER themehdl: CMS_THEME_FILE_SYSTEM_HANDLER
l_not_found_handler_agent: PROCEDURE [READABLE_STRING_8, WSF_REQUEST, WSF_RESPONSE]
do do
api.logger.put_information (generator + ".configure_api_file_handler", Void) api.logger.put_information (generator + ".configure_api_file_handler", Void)
create themehdl.make (api) l_not_found_handler_agent := agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
themehdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
do do
execute_default (ia_req, ia_res) 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. -- See CMS_API.api.theme_path_for (...) for the hardcoded "/theme/" path.
a_router.handle ("/theme/{theme_id}{/vars}", themehdl, router.methods_GET) a_router.handle ("/theme/{theme_id}{/vars}", themehdl, router.methods_GET)
-- "/files/.." -- "/files/.."
create fhdl.make_hidden_with_path (api.files_location) create fhdl.make_hidden_with_path (api.files_location)
fhdl.disable_index fhdl.disable_index
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE) fhdl.set_not_found_handler (l_not_found_handler_agent)
do
execute_default (ia_req, ia_res)
end)
a_router.handle (api.files_path, fhdl, router.methods_GET) a_router.handle (api.files_path, fhdl, router.methods_GET)
-- files folder from specific module. -- files folder from specific module.
@@ -222,10 +222,7 @@ feature -- Settings: router
-- www folder. Should we keep this?? -- www folder. Should we keep this??
create fhdl.make_hidden_with_path (setup.environment.www_path) create fhdl.make_hidden_with_path (setup.environment.www_path)
fhdl.disable_index fhdl.disable_index
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE) fhdl.set_not_found_handler (l_not_found_handler_agent)
do
execute_default (ia_req, ia_res)
end)
a_router.handle ("/", fhdl, router.methods_GET) a_router.handle ("/", fhdl, router.methods_GET)
end end
@@ -328,7 +325,6 @@ feature -- Execution
local local
ut: FILE_UTILITIES ut: FILE_UTILITIES
p: PATH p: PATH
r: NOT_FOUND_ERROR_CMS_RESPONSE
f: WSF_FILE_RESPONSE f: WSF_FILE_RESPONSE
do do
p := api.theme_assets_location.extended ("favicon.ico") 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 f.set_expires_in_seconds (86_400) -- 24h = 60 sec * 60 min * 24 = 86 400 minutes
res.send (f) res.send (f)
else else
create r.make (req, res, api) api.response_api.send_not_found (Void, req, res)
r.execute
end end
end end
@@ -347,7 +342,6 @@ feature -- Execution
-- i.e: "/module/{modname}/files{/vars}" -- i.e: "/module/{modname}/files{/vars}"
local local
fhdl: WSF_FILE_SYSTEM_HANDLER fhdl: WSF_FILE_SYSTEM_HANDLER
r: NOT_FOUND_ERROR_CMS_RESPONSE
do do
if attached {WSF_STRING} req.path_parameter ("modname") as l_mod_name then 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")) 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) end)
fhdl.execute_starts_with ("/module/" + l_mod_name.url_encoded_value + "/files/", req, res) fhdl.execute_starts_with ("/module/" + l_mod_name.url_encoded_value + "/files/", req, res)
else else
create r.make (req, res, api) api.response_api.send_not_found (Void, req, res)
r.execute
end end
end end
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Default request handler if no other are relevant -- Default request handler if no other are relevant
local
r: NOT_FOUND_ERROR_CMS_RESPONSE
do do
to_implement ("Default response for CMS_SERVICE") to_implement ("Default response for CMS_SERVICE")
create r.make (req, res, api) api.response_api.send_not_found (Void, req, res)
r.execute
end end
note note
+64 -14
View File
@@ -6,7 +6,7 @@ note
class class
CMS_FILE_SYSTEM_UTILITIES CMS_FILE_SYSTEM_UTILITIES
feature -- Files feature -- File path
relative_path_inside (a_path: PATH; a_root_path: PATH): detachable 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`. -- 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
end end
feature -- Read
files_from_location (a_loc: PATH; is_recursive: BOOLEAN): detachable LIST [PATH] files_from_location (a_loc: PATH; is_recursive: BOOLEAN): detachable LIST [PATH]
local local
d: DIRECTORY d: DIRECTORY
@@ -82,13 +84,14 @@ feature -- Files
retry retry
end end
feature -- Read/Write
safe_copy_file (src,dst: PATH): BOOLEAN safe_copy_file (src,dst: PATH): BOOLEAN
-- Copy file from `src` to `dst' -- Copy file from `src` to `dst'
-- and return True on success, False on failure. -- and return True on success, False on failure.
local local
retried: BOOLEAN retried: BOOLEAN
f_src, f_dst: RAW_FILE f_src, f_dst: RAW_FILE
d: DIRECTORY
do do
Result := False Result := False
if retried then if retried then
@@ -96,20 +99,45 @@ feature -- Files
else else
create f_src.make_with_path (src) create f_src.make_with_path (src)
if f_src.exists and then f_src.is_access_readable then if f_src.exists and then f_src.is_access_readable then
if attached dst.parent as l_parent then if safe_create_parent_directory (dst) then
create d.make_with_path (l_parent) create f_dst.make_with_path (dst)
if not d.exists then if not f_dst.exists or else f_dst.is_access_writable then
d.recursive_create_dir 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
else
Result := False -- No parent directory!
end end
create f_dst.make_with_path (dst) end
if not f_dst.exists or else f_dst.is_access_writable then end
f_src.open_read rescue
f_dst.open_write retried := True
f_src.copy_to (f_dst) retry
f_dst.close end
f_src.close
Result := True -- Succeed! 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 end
end end
@@ -118,6 +146,28 @@ feature -- Files
retry retry
end 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 note
copyright: "2011-2017, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
@@ -45,7 +45,10 @@ feature -- HTTP Methods
lst: ARRAYED_LIST [CMS_MODULE] lst: ARRAYED_LIST [CMS_MODULE]
l_access: detachable READABLE_STRING_8 l_access: detachable READABLE_STRING_8
l_denied: BOOLEAN l_denied: BOOLEAN
l_is_fresh_installation: BOOLEAN
do do
l_is_fresh_installation := api.enabled_modules.count <= 1 --| Should have at least the required Core module!
--| FIXME: improve the installer. --| FIXME: improve the installer.
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
l_access := api.setup.string_8_item ("admin.installation_access") l_access := api.setup.string_8_item ("admin.installation_access")
@@ -62,8 +65,7 @@ feature -- HTTP Methods
l_denied := True l_denied := True
end end
if l_denied then if l_denied then
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) send_custom_access_denied ("You do not have permission to access CMS installation procedure!", Void, req, res)
r.set_main_content ("You do not have permission to access CMS installation procedure!")
else else
create s.make_from_string ("<h1>Modules</h1><ul>") create s.make_from_string ("<h1>Modules</h1><ul>")
create lst.make (1) create lst.make (1)
@@ -107,9 +109,14 @@ feature -- HTTP Methods
s.append ("</ul>") s.append ("</ul>")
s.append ("<div>Back to the " + r.link ("Administration", api.administration_path (Void), Void) + " ...</div>") s.append ("<div>Back to the " + r.link ("Administration", api.administration_path (Void), Void) + " ...</div>")
r.set_main_content (s) 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 end
r.set_title (r.translation ("CMS Installation ...", Void))
r.execute
end end
note note
+14 -21
View File
@@ -29,7 +29,7 @@ feature -- API Service
api: CMS_API api: CMS_API
feature -- Response helpers feature -- Response message helpers
redirect_to (a_location: READABLE_STRING_8; res: WSF_RESPONSE) redirect_to (a_location: READABLE_STRING_8; res: WSF_RESPONSE)
-- Send via `res' a redirection message for location `a_location'. -- 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) res.send (create {CMS_FORBIDDEN_RESPONSE_MESSAGE}.make)
end end
feature -- Response helpers
send_access_denied (req: WSF_REQUEST; res: WSF_RESPONSE) send_access_denied (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Forbidden response. -- Forbidden response.
local
r: CMS_RESPONSE
do do
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_access_denied (Void, req, res)
r.execute 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 end
send_not_found (req: WSF_REQUEST; res: WSF_RESPONSE) send_not_found (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Send via `res' a not found response. -- Send via `res' a not found response.
local
r: CMS_RESPONSE
do do
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_not_found (Void, req, res)
r.execute
end end
send_bad_request (req: WSF_REQUEST; res: WSF_RESPONSE) send_bad_request (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Send via `res' a bad request response. -- Send via `res' a bad request response.
local
r: CMS_RESPONSE
do do
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_bad_request (Void, req, res)
r.execute
end end
send_not_implemented (a_message: detachable READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE) send_not_implemented (a_message: detachable READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
-- Send via `res' a not implemented response. -- Send via `res' a not implemented response.
local
r: CMS_RESPONSE
do do
create {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE} r.make (req, res, api) api.response_api.send_not_implemented (a_message, req, res)
if a_message /= Void then
r.set_main_content (a_message)
end
r.execute
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end
@@ -28,7 +28,6 @@ feature -- Execution
-- Execute `req' responding in `res'. -- Execute `req' responding in `res'.
local local
fhdl: WSF_FILE_SYSTEM_HANDLER fhdl: WSF_FILE_SYSTEM_HANDLER
not_found: NOT_FOUND_ERROR_CMS_RESPONSE
do do
if attached {WSF_STRING} req.path_parameter ("theme_id") as l_theme_id then 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)) 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 elseif attached not_found_handler as h then
h.call (req.percent_encoded_path_info, req, res) h.call (req.percent_encoded_path_info, req, res)
else else
create not_found.make (req, res, api) api.response_api.send_not_found (Void, req, res)
not_found.execute
end end
end end
+9 -5
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 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. -- Region associated with `a_block_id' in configuration, if any.
do 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 end
feature -- Block management feature -- Block management
@@ -1119,9 +1119,14 @@ feature -- Generation
add_to_primary_menu (lnk) add_to_primary_menu (lnk)
api.hooks.invoke_menu_system_alter (menu_system, Current) 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! -- 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 end
-- Blocks -- Blocks
@@ -1454,7 +1459,6 @@ feature {NONE} -- Execution
local local
cms_page: CMS_HTML_PAGE cms_page: CMS_HTML_PAGE
page: CMS_HTML_PAGE_RESPONSE page: CMS_HTML_PAGE_RESPONSE
utf: UTF_CONVERTER
h: HTTP_HEADER h: HTTP_HEADER
l_new_location: detachable READABLE_STRING_8 l_new_location: detachable READABLE_STRING_8
l_redirection_delay: like redirection_delay l_redirection_delay: like redirection_delay
@@ -1473,7 +1477,7 @@ feature {NONE} -- Execution
end end
if attached {READABLE_STRING_GENERAL} optional_content_type as l_type then 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 else
create cms_page.make create cms_page.make
end end
+87
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
@@ -14,7 +14,16 @@ inherit
end end
create 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 feature -- Generation
@@ -26,17 +35,75 @@ feature -- Generation
page.register_variable (status_code.out, "code") page.register_variable (status_code.out, "code")
end 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 feature -- Execution
process process
-- Computed response message. -- Computed response message.
local
s: STRING
do do
set_title ("Forbidden") set_title ("Forbidden")
set_page_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 end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end
+11
View File
@@ -126,6 +126,17 @@ feature -- Access: user
Result := storage.recent_users (params.offset.to_integer_32, params.size.to_integer_32) Result := storage.recent_users (params.offset.to_integer_32, params.size.to_integer_32)
end 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 feature -- Change User
new_user (a_user: CMS_USER) new_user (a_user: CMS_USER)
+1 -1
View File
@@ -47,7 +47,7 @@ feature -- Access
page_html (page: CMS_HTML_PAGE): STRING_8 page_html (page: CMS_HTML_PAGE): STRING_8
do do
to_implement ("Add a better response message, maybe using smarty template") to_implement ("Add a better response message, maybe using smarty template")
Result := "Service Unavailable" Result := "Service Unavailable (missing theme!)"
end end
note note
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
+1 -2
View File
@@ -40,7 +40,6 @@ feature -- Access
regions: ARRAY [STRING] regions: ARRAY [STRING]
local local
i: INTEGER i: INTEGER
utf: UTF_CONVERTER
l_regions: like internal_regions l_regions: like internal_regions
do do
l_regions := internal_regions l_regions := internal_regions
@@ -51,7 +50,7 @@ feature -- Access
across across
tb as ic tb as ic
loop 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 i := i + 1
end end
else else
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?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> <description>Integration project including many lib</description>
<target name="all"> <target name="all">
<root all_classes="true"/> <root all_classes="true"/>