Fixed and improved various issue in admin module (especially the Role editing which was not working as expected.)

Added CMS_MODULE.permissions to allow module to declare the potential permissions.
Added support for CMS_LINK.is_forbidden, in relation with CMS_LOCAL_LINK.permission_arguments.
Split link "username (Logout)" into 2 links "username" and "logout".
Fixed/Changed the way auth modules alter the logout link based on "(Logout)" title, by safer solution based on `location' of the link.

Fixed usage of WSF_REQUEST.path_info by using percent_encoded_path_info which is not non unicode path info to be used most of the time.
Merged CMS_REPONSE.variables and CMS_REPONSE.values .
When possible, prefer usage of CMS_RESPONSE.user instead of CMS_REQUEST_UTIL.current_user (WSF_REQUEST) whenever it is possible.
When possible, prefer usage of CMS_RESPONSE.location, rather than usage of WSF_REQUEST.(percent_encoded_)path_info .
Code cleaning.
This commit is contained in:
2015-08-04 12:48:14 +02:00
parent c271f839e2
commit bba1d57ce3
38 changed files with 497 additions and 594 deletions

View File

@@ -171,6 +171,13 @@ feature -- Access: roles and permissions
deferred
end
role_permissions: LIST [READABLE_STRING_8]
-- Possible known role permissions.
deferred
ensure
object_comparison: Result.object_comparison
end
feature -- Change: roles and permissions
save_user_role (a_user_role: CMS_USER_ROLE)

View File

@@ -99,6 +99,12 @@ feature -- Access: roles and permissions
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
end
role_permissions: LIST [READABLE_STRING_8]
-- Possible known permissions.
do
create {ARRAYED_LIST [READABLE_STRING_8]} Result.make (0)
end
feature -- Change: roles and permissions
save_user_role (a_user_role: CMS_USER_ROLE)

View File

@@ -503,6 +503,27 @@ feature -- Access: roles and permissions
end
end
role_permissions: LIST [READABLE_STRING_8]
-- Possible known permissions.
do
error_handler.reset
write_information_log (generator + ".role_permissions")
create {ARRAYED_LIST [READABLE_STRING_8]} Result.make (0)
Result.compare_objects
from
sql_query (select_role_permissions, Void)
sql_start
until
sql_after
loop
if attached sql_read_string (1) as l_permission then
Result.force (l_permission)
end
sql_forth
end
end
feature -- Change: roles and permissions
save_user_role (a_user_role: CMS_USER_ROLE)
@@ -553,18 +574,7 @@ feature -- Change: roles and permissions
a_user_role.permissions as ic
loop
p := ic.item
from
l_found := False
l_permissions.start
until
l_found or l_permissions.after
loop
if p.is_case_insensitive_equal (l_permissions.item) then
l_found := True
else
l_permissions.forth
end
end
l_found := across l_permissions as p_ic some p.is_case_insensitive_equal_general (p_ic.item) end
if l_found then
-- Already there, skip
else
@@ -915,6 +925,9 @@ feature {NONE} -- Sql Queries: USER ROLE
select_role_permissions_by_role_id: STRING = "SELECT permission, module FROM role_permissions WHERE rid=:rid;"
-- User role permissions for role id :rid;
select_role_permissions: STRING = "SELECT DISTINCT permission FROM role_permissions;"
-- Used user role permissions
sql_delete_role_permissions_by_role_id: STRING = "DELETE FROM role_permissions WHERE rid=:rid;"
sql_delete_role_by_id: STRING = "DELETE FROM roles WHERE rid=:rid;"

View File

@@ -32,6 +32,14 @@ feature -- Access
dependencies: detachable LIST [TYPE [CMS_MODULE]]
-- Optional dependencies.
permissions: LIST [READABLE_STRING_8]
-- List of permission ids, used by this module, and declared.
require
is_initialized: is_initialized
do
create {ARRAYED_LIST [READABLE_STRING_8]} Result.make (0)
end
feature {CMS_API} -- Module Initialization
initialize (api: CMS_API)

View File

@@ -25,6 +25,7 @@ feature -- User
current_user (req: WSF_REQUEST): detachable CMS_USER
-- Current user or Void in case of Guest user.
-- note: if a CMS_RESPONSE is available, always prefer {CMS_RESPONSE}.user if relevant.
note
EIS: "eiffel:?class=AUTHENTICATION_FILTER&feature=execute"
do
@@ -70,4 +71,7 @@ feature -- Media Type
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -194,9 +194,14 @@ feature -- Access: CMS
values: CMS_VALUE_TABLE
-- Associated values indexed by string name.
feature -- User access
is_authenticated: BOOLEAN
-- Is user authenticated?
do
Result := user /= Void
end
user: detachable CMS_USER
do
Result := current_user (request)
@@ -204,16 +209,28 @@ feature -- User access
feature -- Permission
has_permission_on_link (a_link: CMS_LINK): BOOLEAN
-- Does current user has permission to access link `a_link'?
do
Result := True
if
attached {CMS_LOCAL_LINK} a_link as lnk and then
attached lnk.permission_arguments as l_perms
then
Result := has_permissions (l_perms)
end
end
has_permission (a_permission: READABLE_STRING_GENERAL): BOOLEAN
-- Does current user has permission `a_permission' ?
do
Result := user_has_permission (current_user (request), a_permission)
Result := user_has_permission (user, a_permission)
end
has_permissions (a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
-- Does current user has any of the permissions `a_permission_list' ?
do
Result := user_has_permissions (current_user (request), a_permission_list)
Result := user_has_permissions (user, a_permission_list)
end
user_has_permission (a_user: detachable CMS_USER; a_permission: READABLE_STRING_GENERAL): BOOLEAN
@@ -296,6 +313,12 @@ feature -- Element change
main_content := s
end
add_variable (a_element: ANY; a_key:READABLE_STRING_32)
obsolete "Use `set_value' [Aug/2015]"
do
set_value (a_element, a_key)
end
set_value (v: detachable ANY; k: READABLE_STRING_GENERAL)
-- Set value `v' associated with name `k'.
do
@@ -859,15 +882,16 @@ feature -- Generation
prepare (page: CMS_HTML_PAGE)
local
lnk: CMS_LINK
l_menu_list_prepared: ARRAYED_LIST [CMS_LINK_COMPOSITE]
do
-- Menu
create {CMS_LOCAL_LINK} lnk.make ("Home", "")
lnk.set_weight (-10)
add_to_primary_menu (lnk)
invoke_menu_system_alter (menu_system)
prepare_menu_system (menu_system)
-- Blocks
create l_menu_list_prepared.make (0)
get_blocks
across
regions as reg_ic
@@ -876,11 +900,23 @@ feature -- Generation
reg_ic.item.blocks as ic
loop
if attached {CMS_MENU_BLOCK} ic.item as l_menu_block then
recursive_get_active (l_menu_block.menu, request)
l_menu_list_prepared.force (l_menu_block.menu)
prepare_links (l_menu_block.menu)
end
end
end
-- Prepare menu not in a block.
across
menu_system as ic
loop
if not l_menu_list_prepared.has (ic.item) then
l_menu_list_prepared.force (ic.item)
prepare_links (ic.item)
end
end
l_menu_list_prepared.wipe_out -- Clear for memory purpose.
-- Sort items
across menu_system as ic loop
ic.item.sort
@@ -951,7 +987,7 @@ feature -- Generation
page.set_title (title)
debug ("cms")
if title = Void then
page.set_title ("CMS::" + request.path_info) --| FIXME: probably, should be removed and handled by theme.
page.set_title ({STRING_32} "CMS::" + request.path_info) --| FIXME: probably, should be removed and handled by theme.
end
end
@@ -988,54 +1024,19 @@ feature -- Generation
do
end
prepare_menu_system (a_menu_system: CMS_MENU_SYSTEM)
do
across
a_menu_system as c
loop
prepare_links (c.item)
end
end
prepare_links (a_menu: CMS_LINK_COMPOSITE)
local
to_remove: ARRAYED_LIST [CMS_LINK]
do
create to_remove.make (0)
across
a_menu as c
loop
if attached {CMS_LOCAL_LINK} c.item as lm then
-- if attached lm.permission_arguments as perms and then not has_permissions (perms) then
-- to_remove.force (lm)
-- else
-- if lm.permission_arguments is Void , this is permitted
get_local_link_active_status (lm)
if attached {CMS_LINK_COMPOSITE} lm as comp then
prepare_links (comp)
end
-- end
elseif attached {CMS_LINK_COMPOSITE} c.item as comp then
prepare_links (comp)
end
end
across
to_remove as c
loop
a_menu.remove (c.item)
end
end
recursive_get_active (a_comp: CMS_LINK_COMPOSITE; req: WSF_REQUEST)
prepare_links (a_comp: CMS_LINK_COMPOSITE)
-- Update the active status recursively on `a_comp'.
local
to_remove: ARRAYED_LIST [CMS_LINK]
ln: CMS_LINK
l_comp_link: detachable CMS_LOCAL_LINK
do
if attached {CMS_LOCAL_LINK} a_comp as lnk then
l_comp_link := lnk
get_local_link_active_status (lnk)
end
if attached a_comp.items as l_items then
create to_remove.make (0)
across
l_items as ic
loop
@@ -1043,15 +1044,27 @@ feature -- Generation
if attached {CMS_LOCAL_LINK} ln as l_local then
get_local_link_active_status (l_local)
end
if (ln.is_expanded or ln.is_collapsed) and then attached {CMS_LINK_COMPOSITE} ln as l_comp then
recursive_get_active (l_comp, req)
end
if l_comp_link /= Void then
if ln.is_expanded or (not ln.is_expandable and ln.is_active) then
l_comp_link.set_expanded (True)
if ln.is_forbidden then
to_remove.force (ln)
else
if
(ln.is_expanded or ln.is_collapsed) and then
attached {CMS_LINK_COMPOSITE} ln as l_comp
then
prepare_links (l_comp)
end
if l_comp_link /= Void then
if ln.is_expanded or (not ln.is_expandable and ln.is_active) then
l_comp_link.set_expanded (True)
end
end
end
end
across
to_remove as ic
loop
a_comp.remove (ic.item)
end
end
if l_comp_link /= Void and then l_comp_link.is_active then
l_comp_link.set_expanded (True)
@@ -1077,25 +1090,7 @@ feature -- Generation
l_is_active := qs.same_string (a_lnk.location)
end
a_lnk.set_is_active (l_is_active)
end
feature -- Custom Variables
variables: detachable STRING_TABLE[ANY]
-- Custom variables to feed the templates.
feature -- Element change: Add custom variables.
add_variable (a_element: ANY; a_key:READABLE_STRING_32)
local
l_variables: like variables
do
l_variables := variables
if l_variables = Void then
create l_variables.make (5)
variables := l_variables
end
l_variables.force (a_element, a_key)
a_lnk.set_is_forbidden (not has_permission_on_link (a_lnk))
end
feature -- Execution

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
page.register_variable (absolute_url (request.path_info, Void), "request")
page.register_variable (absolute_url (request.percent_encoded_path_info, Void), "request")
page.set_status_code ({HTTP_STATUS_CODE}.bad_request)
page.register_variable (page.status_code.out, "code")
end
@@ -35,4 +35,7 @@ feature -- Execution
set_main_content ("<em>Bad request.</em>")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
page.register_variable (absolute_url (request.path_info, Void), "request")
page.register_variable (absolute_url (request.percent_encoded_path_info, Void), "request")
page.set_status_code ({HTTP_STATUS_CODE}.forbidden)
page.register_variable (page.status_code.out, "code")
end
@@ -34,5 +34,8 @@ feature -- Execution
set_page_title ("Forbidden")
set_main_content ("<em>Access denied for resource <strong>" + request.request_uri + "</strong>.</em>")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
page.register_variable (absolute_url (request.path_info, Void), "request")
page.register_variable (absolute_url (location, Void), "request")
page.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
page.register_variable (page.status_code.out, "code")
end
@@ -34,5 +34,8 @@ feature -- Execution
set_page_title (Void)
set_main_content ("<em>Internal Server Error</em>")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
page.register_variable (absolute_url (request.path_info, Void), "request")
page.register_variable (absolute_url (request.percent_encoded_path_info, Void), "request")
page.set_status_code ({HTTP_STATUS_CODE}.not_found)
page.register_variable (page.status_code.out, "code")
end
@@ -34,5 +34,8 @@ feature -- Execution
set_page_title ("Not Found")
set_main_content ("<em>The requested page could not be found.</em>")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
page.register_variable (absolute_url (request.path_info, Void), "request")
page.register_variable (absolute_url (request.percent_encoded_path_info, Void), "request")
page.set_status_code ({HTTP_STATUS_CODE}.not_implemented)
page.register_variable (page.status_code.out, "code")
end
@@ -36,5 +36,8 @@ feature -- Execution
set_main_content (request.percent_encoded_path_info + " is not implemented!")
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -7,24 +7,11 @@ class
GENERIC_VIEW_CMS_RESPONSE
inherit
CMS_RESPONSE
redefine
custom_prepare
end
create
make
feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
if attached variables as l_variables then
across l_variables as c loop page.register_variable (c.item, c.key) end
end
end
feature -- Execution
process

View File

@@ -1,6 +1,5 @@
note
description: "Summary description for {CMS_USER_API}."
author: ""
description: "API providing user related features."
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
@@ -143,12 +142,52 @@ feature -- User roles.
Result := storage.user_role_by_name (a_name)
end
role_permissions: LIST [READABLE_STRING_8]
-- Possible known permissions.
local
perm: READABLE_STRING_8
do
Result := storage.role_permissions
across
cms_api.enabled_modules as ic
loop
across
ic.item.permissions as perms_ic
loop
perm := perms_ic.item
if not Result.has (perm) then
Result.force (perm)
end
end
end
end
roles: LIST [CMS_USER_ROLE]
-- List of possible roles.
do
Result := storage.user_roles
end
effective_roles: LIST [CMS_USER_ROLE]
-- List of possible roles, apart from anonymous and authenticated roles that are special.
local
l_roles: like roles
r: CMS_USER_ROLE
do
l_roles := storage.user_roles
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (l_roles.count)
across
l_roles as ic
loop
r := ic.item
if r.same_user_role (anonymous_user_role) or r.same_user_role (authenticated_user_role) then
-- Ignore
else
Result.force (r)
end
end
end
roles_count: INTEGER
-- Number of roles
do

View File

@@ -266,19 +266,24 @@ feature -- Convertion
pagination_links as ic
loop
lnk := ic.item
if lnk.is_active then
a_output.append ("<li class=%"active%">")
elseif lnk.title.same_string (label_previous) then
a_output.append ("<li class=%"previous%">")
elseif lnk.title.same_string (label_next) then
a_output.append ("<li class=%"next%">")
else
a_output.append ("<li>")
if not lnk.is_forbidden then
if lnk.is_active then
a_output.append ("<li class=%"active%">")
elseif lnk.title.same_string (label_previous) then
a_output.append ("<li class=%"previous%">")
elseif lnk.title.same_string (label_next) then
a_output.append ("<li class=%"next%">")
else
a_output.append ("<li>")
end
a_output.append (a_response.link (lnk.title, lnk.location, Void))
a_output.append ("</li>")
end
a_output.append (a_response.link (lnk.title, lnk.location, Void))
a_output.append ("</li>")
end
a_output.append ("</ul>")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -148,46 +148,45 @@ feature {NONE} -- Implementation
local
cl: STRING
do
debug ("refactor_fixme")
fixme ("Remove HTML from Eiffel")
end
create cl.make_empty
if lnk.is_active then
cl.append ("active ")
end
if lnk.is_expandable then
cl.append ("expandable ")
end
if lnk.is_expanded then
cl.append ("expanded ")
end
if cl.is_empty then
s.append ("<li>")
else
s.append ("<li class=%""+ cl + "%">")
end
s.append ("<a href=%"")
s.append (url (lnk.location, Void))
s.append ("%">")
s.append (html_encoded (lnk.title))
s.append ("</a>")
if
(lnk.is_expanded or lnk.is_collapsed) and then
attached lnk.children as l_children
then
s.append ("<ul>%N")
across
l_children as c
loop
append_cms_link_to (c.item, s)
if not lnk.is_forbidden then
create cl.make_empty
if lnk.is_active then
cl.append ("active ")
end
s.append ("</ul>")
if lnk.is_expandable then
cl.append ("expandable ")
end
if lnk.is_expanded then
cl.append ("expanded ")
end
if cl.is_empty then
s.append ("<li>")
else
s.append ("<li class=%""+ cl + "%">")
end
s.append ("<a href=%"")
s.append (url (lnk.location, Void))
s.append ("%">")
s.append (html_encoded (lnk.title))
s.append ("</a>")
if
(lnk.is_expanded or lnk.is_collapsed) and then
attached lnk.children as l_children
then
s.append ("<ul>%N")
across
l_children as c
loop
append_cms_link_to (c.item, s)
end
s.append ("</ul>")
end
s.append ("</li>")
end
s.append ("</li>")
end
note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software