Implemented Module enable/disable setting from configuration.

Implemented dependencies checking to set CMS_MODULE.is_enabled.
Implemented the persistence of CMS_USER.roles
This commit is contained in:
2015-07-10 18:46:16 +02:00
parent 779064a505
commit 7f4a7b3ab9
13 changed files with 258 additions and 56 deletions

View File

@@ -12,3 +12,14 @@ theme=bootstrap
smtp=localhost:25
#sendmail=/usr/bin/sendmail
#output=@stderr
[modules]
*=off
auth=on
basic_auth=on
blog=on
debug=on
demo=on
node=on
oauth20=on
openid=on

View File

@@ -55,38 +55,32 @@ feature -- CMS setup
local
m: CMS_MODULE
do
-- Auth
create {CMS_AUTHENTICATION_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_BASIC_AUTH_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_OAUTH_20_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_OPENID_MODULE} m.make
m.enable
a_setup.register_module (m)
-- Nodes
create {CMS_NODE_MODULE} m.make (a_setup)
m.enable
a_setup.register_module (m)
create {CMS_BLOG_MODULE} m.make
m.enable
a_setup.register_module (m)
-- Miscellanious
create {CMS_DEBUG_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_DEMO_MODULE} m.make
m.enable
a_setup.register_module (m)
end
end

View File

@@ -37,7 +37,8 @@ feature {NONE} -- Initialization
do
version := "1.0"
description := "Service to manage basic authentication"
package := "core"
package := "authentication"
add_dependency ({CMS_AUTHENTICATION_MODULE})
end
feature -- Access

View File

@@ -32,6 +32,7 @@ feature {NONE} -- Initialization
version := "1.0"
description := "Service to demonstrate new node for blog"
package := "demo"
add_dependency ({CMS_NODE_MODULE})
end
feature -- Access

View File

@@ -49,7 +49,9 @@ feature {NONE} -- Initialization
do
version := "1.0"
description := "OAuth20 module"
package := "Oauth20"
package := "authentication"
add_dependency ({CMS_AUTHENTICATION_MODULE})
create root_dir.make_current
cache_duration := 0

View File

@@ -51,7 +51,8 @@ feature {NONE} -- Initialization
do
version := "1.0"
description := "Openid module"
package := "openid"
package := "authentication"
add_dependency ({CMS_AUTHENTICATION_MODULE})
create root_dir.make_current
cache_duration := 0

View File

@@ -103,25 +103,7 @@ feature {NONE} -- Initialization
initialize_modules
-- Intialize core modules.
local
-- m: CMS_MODULE
do
-- Core
-- create {BASIC_AUTH_MODULE} m.make
-- m.enable
-- register_module (m)
-- create {USER_MODULE} m.make (Current)
-- m.enable
-- register_module (m)
-- create {ADMIN_MODULE} m.make (Current)
-- m.enable
-- register_module (m)
-- create {NODE_MODULE} m.make (Current)
-- m.enable
-- register_module (m)
end
feature {NONE} -- Configuration

View File

@@ -33,16 +33,74 @@ feature -- Access
modules as ic
loop
l_module := ic.item
update_module_status_from_configuration (l_module)
if l_module.is_enabled then
Result.extend (l_module)
end
end
across
Result as ic
loop
l_module := ic.item
update_module_status_within (l_module, Result)
if not l_module.is_enabled then
Result.remove (l_module)
end
end
ensure
only_enabled_modules: across Result as ic all ic.item.is_enabled end
end
feature {CMS_MODULE, CMS_API} -- Restricted access
update_module_status_within (a_module: CMS_MODULE; a_collection: CMS_MODULE_COLLECTION)
-- Is `a_module' enabled, and also its dependencies within the collection `a_collection'?
require
a_module_is_enabled: a_module.is_enabled
do
if attached a_module.dependencies as deps then
across
deps as ic
until
not a_module.is_enabled
loop
if
attached a_collection.item (ic.item) as mod and then
mod.is_enabled
then
update_module_status_within (mod, a_collection)
else
--| dependency not found or disabled
a_module.disable
end
end
end
end
update_module_status_from_configuration (m: CMS_MODULE)
-- Is module `m' enabled?
local
b: BOOLEAN
dft: BOOLEAN
do
-- By default enabled.
if false and attached text_item ("modules.*") as l_mod_status then
dft := l_mod_status.is_case_insensitive_equal_general ("on")
else
dft := True
end
if attached text_item ("modules." + m.name) as l_mod_status then
b := l_mod_status.is_case_insensitive_equal_general ("on")
else
b := dft
end
if b then
m.enable
else
m.disable
end
end
modules: CMS_MODULE_COLLECTION
-- List of available modules.
deferred

View File

@@ -57,7 +57,6 @@ feature -- Initialization
l_authenticated_role.add_permission ("delete own page")
l_authenticated_role.add_permission ("trash own page")
a_storage.save_user_role (l_authenticated_role)
end
note

View File

@@ -194,8 +194,13 @@ feature -- Change: user
sql_change (sql_insert_user, l_parameters)
if not error_handler.has_error then
a_user.set_id (last_inserted_user_id)
update_user_roles (a_user)
end
if not error_handler.has_error then
sql_commit_transaction
else
sql_rollback_transaction
end
sql_commit_transaction
else
-- set error
error_handler.add_custom_error (-1, "bad request" , "Missing password or email")
@@ -224,6 +229,8 @@ feature -- Change: user
l_password_hash /= Void and l_password_salt /= Void and
attached a_user.email as l_email
then
sql_begin_transaction
write_information_log (generator + ".update_user")
create l_parameters.make (6)
l_parameters.put (a_user.id, "uid")
@@ -235,12 +242,101 @@ feature -- Change: user
l_parameters.put (a_user.status, "status")
sql_change (sql_update_user, l_parameters)
if not error_handler.has_error then
update_user_roles (a_user)
end
if not error_handler.has_error then
sql_commit_transaction
else
sql_rollback_transaction
end
else
-- set error
error_handler.add_custom_error (-1, "bad request" , "Missing password or email")
end
end
update_user_roles (a_user: CMS_USER)
-- Update roles of `a_user'
require
a_user.has_id
local
l_roles, l_existing_roles: detachable LIST [CMS_USER_ROLE]
l_has_role: BOOLEAN
do
l_roles := a_user.roles
if l_roles = Void then
create {ARRAYED_LIST [CMS_USER_ROLE]} l_roles.make (0)
end
sql_begin_transaction
l_existing_roles:= user_roles_for (a_user)
across
l_existing_roles as ic
until
error_handler.has_error
loop
from
l_has_role := False
l_roles.start
until
l_has_role
loop
if l_roles.item.id = ic.item.id then
l_has_role := True
l_roles.remove -- Already stored.
else
l_roles.forth
end
end
if l_has_role then
-- Existing role has to be removed!
unassign_role_from_user (ic.item, a_user)
end
end
across
l_roles as ic
until
error_handler.has_error
loop
-- New role.
assign_role_to_user (ic.item, a_user)
end
if not error_handler.has_error then
sql_commit_transaction
else
sql_rollback_transaction
end
end
assign_role_to_user (a_role: CMS_USER_ROLE; a_user: CMS_USER)
require
a_user.has_id
a_role.has_id
local
l_parameters: STRING_TABLE [detachable ANY]
do
create l_parameters.make (2)
l_parameters.put (a_user.id, "uid")
l_parameters.put (a_role.id, "rid")
sql_change (sql_insert_role_to_user, l_parameters)
end
unassign_role_from_user (a_role: CMS_USER_ROLE; a_user: CMS_USER)
require
a_user.has_id
a_role.has_id
local
l_parameters: STRING_TABLE [detachable ANY]
do
create l_parameters.make (2)
l_parameters.put (a_user.id, "uid")
l_parameters.put (a_role.id, "rid")
sql_change (sql_delete_role_from_user, l_parameters)
end
feature -- Access: roles and permissions
user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
@@ -710,9 +806,15 @@ feature {NONE} -- Sql Queries: USER ROLE
sql_update_user_role : STRING = "UPDATE roles SET name=:name WHERE rid=:rid;"
-- Update user role with id :rid.
select_user_roles_by_user_id: STRING = "SELECT rid, name FROM roles INNER JOIN users_roles ON users_roles.rid=roles.rid WHERE users_roles.uid=:uid;"
select_user_roles_by_user_id: STRING = "SELECT users_roles.rid, roles.name FROM roles INNER JOIN users_roles ON users_roles.rid=roles.rid WHERE users_roles.uid=:uid;"
-- List of user roles for user id :uid.
sql_insert_role_to_user: STRING = "INSERT INTO users_roles (uid, rid) VALUES (:uid, :rid);"
sql_delete_role_from_user: STRING = "DELETE FROM users_roles WHERE uid=:uid AND rid=:rid;"
sql_select_roles_ids_for_user: STRING = "SELECT rid FROM users_roles WHERE uid=:uid;"
select_user_role_by_id: STRING = "SELECT rid, name FROM roles WHERE rid=:rid;"
-- User role for role id :rid;
@@ -753,4 +855,7 @@ feature {NONE} -- User Password Recovery
Select_user_by_password_token: STRING = "SELECT u.* FROM users as u JOIN users_password_recovery as ua ON ua.uid = u.uid and ua.token = :token;"
-- Retrieve user by password token if exist.
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

@@ -200,29 +200,10 @@ feature -- Query: module
module (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE
-- Enabled module typed `a_type', if any.
--| usage: if attached module ({FOO_MODULE}) as mod then ...
local
l_type: TYPE [detachable CMS_MODULE]
do
across
setup.modules as ic
until
Result /= Void
loop
Result := ic.item
if not Result.is_enabled then
Result := Void
else
l_type := Result.generating_type
if a_type ~ l_type then
-- Found
elseif
attached a_type.attempt (Result) and then attached l_type.generating_type.attempt (a_type)
then
-- Found
else
Result := Void
end
end
Result := setup.modules.item (a_type)
if Result /= Void and then not Result.is_enabled then
Result := Void
end
ensure
Result /= Void implies (Result.is_enabled) -- and a_type.is_conforming_to (Result.generating_type))

View File

@@ -23,11 +23,15 @@ feature -- Access
-- Description of the module.
package: STRING
--
-- Associated package.
-- Mostly to group modules by package/category.
version: STRING
-- Version od the module?
dependencies: detachable LIST [TYPE [CMS_MODULE]]
-- Optional dependencies.
feature {CMS_API} -- Module Initialization
initialize (api: CMS_API)
@@ -42,6 +46,18 @@ feature {CMS_API} -- Module Initialization
is_initialized: is_initialized
end
add_dependency (m: TYPE [CMS_MODULE])
local
deps: like dependencies
do
deps := dependencies
if deps = Void then
create {ARRAYED_LIST [TYPE [CMS_MODULE]]} deps.make (1)
dependencies := deps
end
deps.force (m)
end
feature -- Status
is_initialized: BOOLEAN

View File

@@ -21,6 +21,54 @@ feature {NONE} -- Initialization
feature -- Access
item (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE
-- Module typed `a_type', if any.
--| usage: if attached {FOO_MODULE} item ({FOO_MODULE}) as mod then ...
local
l_type: TYPE [detachable CMS_MODULE]
do
across
modules as ic
until
Result /= Void
loop
Result := ic.item
l_type := Result.generating_type
if a_type ~ l_type then
-- Found
elseif
-- Hack: use conformance of type, and reverse conformance of type of type.
attached a_type.attempt (Result) and then attached l_type.generating_type.attempt (a_type)
then
-- Found
else
Result := Void
end
end
ensure
Result /= Void implies (Result.is_enabled)
end
item_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_MODULE
-- (first) module named `a_name', if any.
--| usage: if attached {FOO_MODULE} item_by_name ("foo") as mod then ...
do
across
modules as ic
until
Result /= Void
loop
Result := ic.item
if not a_name.is_case_insensitive_equal (Result.name) then
Result := Void
end
end
ensure
Result /= Void implies a_name.is_case_insensitive_equal (Result.name)
end
feature -- Access: iteration
new_cursor: INDEXABLE_ITERATION_CURSOR [CMS_MODULE]
-- <Precursor>
do
@@ -77,4 +125,7 @@ feature {NONE} -- Implementation
modules: ARRAYED_LIST [CMS_MODULE]
-- List of available modules.
;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