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