Implemented CMS storage for user and nodes.

Implemented role and permission storage.
Introduced the CMS_PARTIAL_NODE and CMS_PARTIAL_USER.
Added support for node storage extension
  - storage of data specific to each node content type,
  - in addition to the core CMS_NODE)
  - For now, only implemented for SQL storage.
Note: in current version, CMS_PAGE support is hard coded in the core,
    (as opposed to be only supported by the node module.)
Commented/removed for now, the Web API code to update node summary, title, via REST request.
This commit is contained in:
2015-04-14 11:25:02 +02:00
parent 734f661add
commit 133c243126
46 changed files with 2262 additions and 468 deletions

View File

@@ -0,0 +1,112 @@
note
description: "Proxy on a {CMS_STORAGE_SQL} interface."
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CMS_PROXY_STORAGE_SQL
inherit
CMS_STORAGE_SQL
create
make
feature {NONE} -- Initialization
make (a_sql_storage: like sql_storage)
do
sql_storage := a_sql_storage
end
sql_storage: CMS_STORAGE_SQL
feature -- Access
api: detachable CMS_API
-- Associated CMS api.
do
Result := sql_storage.api
end
feature -- Error handler
error_handler: ERROR_HANDLER
-- Error handler.
do
Result := sql_storage.error_handler
end
feature -- Execution
sql_begin_transaction
do
sql_storage.sql_begin_transaction
end
sql_rollback_transaction
do
sql_storage.sql_rollback_transaction
end
sql_commit_transaction
do
sql_storage.sql_commit_transaction
end
sql_post_execution
-- Post database execution.
-- note: execute after each `sql_query' and `sql_change'.
do
sql_storage.sql_post_execution
end
feature -- Operation
sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
do
sql_storage.sql_query (a_sql_statement, a_params)
end
sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
do
sql_storage.sql_change (a_sql_statement, a_params)
end
feature -- Access
sql_rows_count: INTEGER
-- Number of rows for last sql execution.
do
Result := sql_storage.sql_rows_count
end
sql_start
-- Set the cursor on first element.
do
sql_storage.sql_start
end
sql_after: BOOLEAN
-- Are there no more items to iterate over?
do
Result := sql_storage.sql_after
end
sql_forth
-- Fetch next row from last sql execution, if any.
do
sql_storage.sql_forth
end
sql_valid_item_index (a_index: INTEGER): BOOLEAN
do
Result := sql_storage.sql_valid_item_index (a_index)
end
sql_item (a_index: INTEGER): detachable ANY
do
Result:= sql_storage.sql_item (a_index)
end
end

View File

@@ -22,6 +22,11 @@ feature {NONE} -- Initialization
do
end
feature -- Access
api: detachable CMS_API assign set_api
-- Associated CMS API.
feature -- Status report
is_available: BOOLEAN
@@ -39,6 +44,14 @@ feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
feature -- Element change
set_api (a_api: like api)
-- Set `api' to `a_api'.
do
api := a_api
end
feature -- Misc
-- set_custom_value (a_name: READABLE_STRING_8; a_value: attached like custom_value; a_type: READABLE_STRING_8)

View File

@@ -95,12 +95,20 @@ feature -- Change: user
do
end
feature -- Access: roles and permissions
user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
do
end
user_roles_for (a_user: CMS_USER): LIST [CMS_USER_ROLE]
-- User roles for user `a_user'.
-- Note: anonymous and authenticated roles are not included.
do
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
end
user_roles: LIST [CMS_USER_ROLE]
do
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
@@ -179,4 +187,13 @@ feature -- Node
do
end
feature -- Helpers
fill_node (a_node: CMS_NODE)
-- Fill `a_node' with extra information from database.
-- i.e: specific to each content type data.
do
end
end

View File

@@ -7,6 +7,13 @@ note
deferred class
CMS_STORAGE_SQL
feature -- Access
api: detachable CMS_API
-- Associated CMS api.
deferred
end
feature -- Error handler
error_handler: ERROR_HANDLER
@@ -108,6 +115,54 @@ feature -- Operation
deferred
end
feature -- Helper
sql_execute_file_script (a_path: PATH)
-- Execute SQL script from `a_path'.
local
f: PLAIN_TEXT_FILE
sql: STRING
do
create f.make_with_path (a_path)
if f.exists and then f.is_access_readable then
create sql.make (f.count)
f.open_read
from
f.start
until
f.exhausted or f.end_of_file
loop
f.read_stream_thread_aware (1_024)
sql.append (f.last_string)
end
f.close
sql_execute_script (sql)
end
end
sql_execute_script (a_sql_script: STRING)
-- Execute SQL script.
-- i.e: multiple SQL statements.
do
reset_error
-- sql_begin_transaction
sql_change (a_sql_script, Void)
-- sql_commit_transaction
end
sql_table_exists (a_table_name: READABLE_STRING_8): BOOLEAN
-- Does table `a_table_name' exists?
local
l_params: STRING_TABLE [detachable ANY]
do
reset_error
create l_params.make (1)
l_params.force (a_table_name, "tbname")
sql_query ("SELECT count(*) FROM :tbname ;", l_params)
Result := not has_error
-- FIXME: find better solution
end
feature -- Access
sql_rows_count: INTEGER
@@ -130,7 +185,13 @@ feature -- Access
deferred
end
sql_valid_item_index (a_index: INTEGER): BOOLEAN
deferred
end
sql_item (a_index: INTEGER): detachable ANY
require
valid_index: sql_valid_item_index (a_index)
deferred
end
@@ -160,7 +221,7 @@ feature -- Access
elseif attached {INTEGER_32_REF} l_item as l_value then
Result := l_value.item
else
-- check is_integer_32: False end
check is_integer_32: False end
end
end
@@ -177,7 +238,7 @@ feature -- Access
elseif attached {BOOLEAN_REF} l_item as l_boolean_ref then
Result := l_boolean_ref.item.out
else
-- check is_string: False end
check is_string: False end
end
end
@@ -192,7 +253,9 @@ feature -- Access
Result := l_string
else
if attached sql_read_string (a_index) as s8 then
Result := s8.to_string_32 -- FIXME
Result := s8.to_string_32 -- FIXME: any escape?
else
check is_string_32: False end
end
end
end

View File

@@ -17,6 +17,51 @@ feature -- Error Handling
deferred
end
feature -- Storage extension
register_node_storage_extension (a_extension: CMS_NODE_STORAGE_EXTENSION [CMS_NODE])
-- Register `a_extension' as extension to the node storage system.
local
tb: like node_storage_extensions
do
tb := node_storage_extensions
if tb = Void then
create tb.make_caseless (1)
node_storage_extensions := tb
end
tb.force (a_extension, a_extension.content_type)
end
node_storage_extension (a_node: CMS_NODE): detachable CMS_NODE_STORAGE_EXTENSION [CMS_NODE]
-- Extension to the node storage system for node `a_node'.
do
if attached node_storage_extensions as tb then
Result := tb.item (a_node.content_type)
end
end
feature {NONE} -- Implementation
node_storage_extensions: detachable STRING_TABLE [CMS_NODE_STORAGE_EXTENSION [CMS_NODE]]
-- Table of node storage extensions.
extended_store (a_node: CMS_NODE)
-- Store extended data from `a_node'.
do
if attached node_storage_extension (a_node) as ext then
ext.store_node (a_node)
end
end
extended_load (a_node: CMS_NODE)
-- Load extended data into `a_node'.
do
if attached node_storage_extension (a_node) as ext then
ext.load_node (a_node)
end
end
feature -- Access
nodes_count: INTEGER_64
@@ -44,7 +89,7 @@ feature -- Access
node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
-- Node's author. if any.
require
valid_node: a_id >0
valid_node: a_id > 0
deferred
end
@@ -68,6 +113,15 @@ feature -- Change: Node
deferred
end
update_node (a_node: CMS_NODE)
-- Update node content `a_node'.
-- The user `a_id' is an existing or new collaborator.
require
has_id: a_node.has_id
has_author: attached a_node.author as l_author and then l_author.has_id
deferred
end
delete_node (a_node: CMS_NODE)
-- Delete `a_node'.
do
@@ -83,39 +137,40 @@ feature -- Change: Node
deferred
end
update_node (a_node: CMS_NODE)
-- Update node content `a_node'.
-- The user `a_id' is an existing or new collaborator.
-- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
-- -- Update node title to `a_title', node identified by id `a_node_id'.
-- -- The user `a_user_id' is an existing or new collaborator.
-- require
-- valid_node_id: a_node_id > 0
-- valid_user_id: a_user_id > 0
-- deferred
-- end
-- update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
-- -- Update node summary to `a_summary', node identified by id `a_node_id'.
-- -- The user `a_user_id' is an existing or new collaborator.
-- require
-- valid_id: a_node_id > 0
-- valid_user_id: a_user_id > 0
-- deferred
-- end
-- update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
-- -- Update node content to `a_content', node identified by id `a_node_id'.
-- -- The user `a_user_id' is an existing or new collaborator.
-- require
-- valid_id: a_node_id > 0
-- valid_user_id: a_user_id > 0
-- deferred
-- end
feature -- Helpers
fill_node (a_node: CMS_NODE)
-- Fill `a_node' with extra information from database.
-- i.e: specific to each content type data.
require
has_id: a_node.has_id
has_author: attached a_node.author as l_author and then l_author.has_id
deferred
end
update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
-- Update node title to `a_title', node identified by id `a_node_id'.
-- The user `a_user_id' is an existing or new collaborator.
require
valid_node_id: a_node_id > 0
valid_user_id: a_user_id > 0
deferred
end
update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
-- Update node summary to `a_summary', node identified by id `a_node_id'.
-- The user `a_user_id' is an existing or new collaborator.
require
valid_id: a_node_id > 0
valid_user_id: a_user_id > 0
deferred
end
update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
-- Update node content to `a_content', node identified by id `a_node_id'.
-- The user `a_user_id' is an existing or new collaborator.
require
valid_id: a_node_id > 0
valid_user_id: a_user_id > 0
deferred
end

View File

@@ -0,0 +1,53 @@
note
description: "Node storage extension for specific node descendant."
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_NODE_STORAGE_EXTENSION [G -> CMS_NODE]
feature -- Access
content_type: READABLE_STRING_8
deferred
end
feature -- Status report
is_accepted (a_node: CMS_NODE): BOOLEAN
-- Is `a_node' accepted by current storage extension?
do
Result := attached {G} a_node
end
feature -- Persistence
store_node (a_node: CMS_NODE)
require
a_node_accepted: is_accepted (a_node)
do
if attached {G} a_node as obj then
store (obj)
end
end
load_node (a_node: CMS_NODE)
require
a_node_accepted: is_accepted (a_node)
do
if attached {G} a_node as obj then
load (obj)
end
end
feature {NONE} -- Persistence implementation
store (a_node: G)
deferred
end
load (a_node: G)
deferred
end
end

View File

@@ -1,6 +1,7 @@
note
description: "Summary description for {CMS_NODE_STORAGE_SQL}."
author: ""
description: "[
CMS NODE Storage based on SQL statements.
]"
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
@@ -23,7 +24,7 @@ feature -- Access
do
error_handler.reset
write_information_log (generator + ".nodes_count")
sql_query (select_nodes_count, Void)
sql_query (sql_select_nodes_count, Void)
if sql_rows_count = 1 then
Result := sql_read_integer_64 (1)
end
@@ -38,7 +39,7 @@ feature -- Access
write_information_log (generator + ".nodes")
from
sql_query (select_nodes, Void)
sql_query (sql_select_nodes, Void)
sql_start
until
sql_after
@@ -48,6 +49,11 @@ feature -- Access
end
sql_forth
end
-- across
-- Result as ic
-- loop
-- fill_node (ic.item)
-- end
end
recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
@@ -64,7 +70,7 @@ feature -- Access
create l_parameters.make (2)
l_parameters.put (a_count, "rows")
l_parameters.put (a_lower, "offset")
sql_query (select_recent_nodes, l_parameters)
sql_query (sql_select_recent_nodes, l_parameters)
sql_start
until
sql_after
@@ -84,8 +90,8 @@ feature -- Access
error_handler.reset
write_information_log (generator + ".node")
create l_parameters.make (1)
l_parameters.put (a_id,"id")
sql_query (select_node_by_id, l_parameters)
l_parameters.put (a_id, "nid")
sql_query (sql_select_node_by_id, l_parameters)
if sql_rows_count = 1 then
Result := fetch_node
end
@@ -121,31 +127,14 @@ feature -- Change: Node
new_node (a_node: CMS_NODE)
-- Save node `a_node'.
local
l_parameters: STRING_TABLE [detachable ANY]
do
-- New node
error_handler.reset
write_information_log (generator + ".new_node")
create l_parameters.make (7)
l_parameters.put (a_node.title, "title")
l_parameters.put (a_node.summary, "summary")
l_parameters.put (a_node.content, "content")
l_parameters.put (a_node.publication_date, "publish")
l_parameters.put (a_node.creation_date, "created")
l_parameters.put (a_node.modification_date, "changed")
if
attached a_node.author as l_author and then
l_author.id > 0
then
l_parameters.put (l_author.id, "author")
else
l_parameters.put (0, "author")
end
sql_change (sql_insert_node, l_parameters)
if not error_handler.has_error then
a_node.set_id (last_inserted_node_id)
end
store_node (a_node)
end
update_node (a_node: CMS_NODE)
-- Update node content `a_node'.
do
store_node (a_node)
end
delete_node_by_id (a_id: INTEGER_64)
@@ -161,144 +150,184 @@ feature -- Change: Node
sql_change (sql_delete_node, l_parameters)
end
update_node (a_node: CMS_NODE)
-- Update node content `a_node'.
-- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
-- -- <Precursor>
-- local
-- l_parameters: STRING_TABLE [detachable ANY]
-- do
-- -- FIXME: unused a_user_id !
-- error_handler.reset
-- write_information_log (generator + ".update_node_title")
-- create l_parameters.make (3)
-- l_parameters.put (a_title, "title")
-- l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
-- l_parameters.put (a_node_id, "nid")
-- sql_change (sql_update_node_title, l_parameters)
-- end
-- update_node_summary (a_user_id: Like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
-- -- <Precursor>
-- local
-- l_parameters: STRING_TABLE [detachable ANY]
-- do
-- -- FIXME: unused a_user_id !
-- error_handler.reset
-- write_information_log (generator + ".update_node_summary")
-- create l_parameters.make (3)
-- l_parameters.put (a_summary, "summary")
-- l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
-- l_parameters.put (a_node_id, "nid")
-- sql_change (sql_update_node_summary, l_parameters)
-- end
-- update_node_content (a_user_id: Like {CMS_USER}.id;a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
-- -- <Precursor>
-- local
-- l_parameters: STRING_TABLE [detachable ANY]
-- do
-- -- FIXME: unused a_user_id !
-- error_handler.reset
-- write_information_log (generator + ".update_node_content")
-- create l_parameters.make (3)
-- l_parameters.put (a_content, "content")
-- l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
-- l_parameters.put (a_node_id, "nid")
-- sql_change (sql_update_node_content, l_parameters)
-- end
feature {NONE} -- Implementation
store_node (a_node: CMS_NODE)
local
l_parameters: STRING_TABLE [detachable ANY]
now: DATE_TIME
is_new: BOOLEAN
do
create now.make_now_utc
error_handler.reset
write_information_log (generator + ".update_node")
create l_parameters.make (7)
write_information_log (generator + ".store_node")
create l_parameters.make (8)
l_parameters.put (a_node.content_type, "type")
l_parameters.put (a_node.title, "title")
l_parameters.put (a_node.summary, "summary")
l_parameters.put (a_node.content, "content")
l_parameters.put (a_node.publication_date, "publish")
l_parameters.put (now, "changed")
l_parameters.put (a_node.id, "id")
if attached a_node.author as l_author then
check valid_author: l_author.has_id end
l_parameters.put (l_author.id, "author")
else
l_parameters.put (0, "author")
end
sql_change (sql_update_node, l_parameters)
if not error_handler.has_error then
a_node.set_modification_date (now)
sql_begin_transaction
if a_node.has_id then
is_new := True
-- Update
l_parameters.put (a_node.id, "id")
sql_change (sql_update_node, l_parameters)
if not error_handler.has_error then
a_node.set_revision (a_node.revision + 1) -- FIXME: Should be incremented by one, in same transaction...but check!
a_node.set_modification_date (now)
end
else
is_new := False
-- Store new node
l_parameters.put (a_node.creation_date, "created")
sql_change (sql_insert_node, l_parameters)
if not error_handler.has_error then
a_node.set_modification_date (now)
a_node.set_id (last_inserted_node_id)
a_node.set_revision (1) -- New object.
end
end
extended_store (a_node)
sql_commit_transaction
end
update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
-- FIXME: unused a_user_id !
error_handler.reset
write_information_log (generator + ".update_node_title")
create l_parameters.make (3)
l_parameters.put (a_title, "title")
l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
l_parameters.put (a_node_id, "nid")
sql_change (sql_update_node_title, l_parameters)
end
feature -- Helpers
update_node_summary (a_user_id: Like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
fill_node (a_node: CMS_NODE)
-- Fill `a_node' with extra information from database.
-- i.e: specific to each content type data.
do
-- FIXME: unused a_user_id !
error_handler.reset
write_information_log (generator + ".update_node_summary")
create l_parameters.make (3)
l_parameters.put (a_summary, "summary")
l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
l_parameters.put (a_node_id, "nid")
sql_change (sql_update_node_summary, l_parameters)
end
update_node_content (a_user_id: Like {CMS_USER}.id;a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
-- FIXME: unused a_user_id !
error_handler.reset
write_information_log (generator + ".update_node_content")
create l_parameters.make (3)
l_parameters.put (a_content, "content")
l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
l_parameters.put (a_node_id, "nid")
sql_change (sql_update_node_content, l_parameters)
write_information_log (generator + ".fill_node")
extended_load (a_node)
end
feature {NONE} -- Queries
Select_nodes_count: STRING = "select count(*) from Nodes;"
sql_select_nodes_count: STRING = "SELECT count(*) from Nodes;"
Select_nodes: STRING = "select * from Nodes;"
-- SQL Query to retrieve all nodes.
sql_select_nodes: STRING = "SELECT * from Nodes;"
-- SQL Query to retrieve all nodes.
Select_node_by_id: STRING = "select * from Nodes where nid =:nid order by nid desc, publish desc;"
sql_select_node_by_id: STRING = "SELECT nid, revision, type, title, summary, content, author, publish, created, changed FROM Nodes WHERE nid =:nid ORDER BY revision desc, publish desc LIMIT 1;"
Select_recent_nodes: STRING = "select * from Nodes order by nid desc, publish desc LIMIT :rows OFFSET :offset ;"
sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, author, publish, created, changed FROM Nodes ORDER BY nid desc, publish desc LIMIT :rows OFFSET :offset ;"
SQL_Insert_node: STRING = "insert into nodes (title, summary, content, publish, created, changed, author) values (:title, :summary, :content, :publish, :created, :changed, :author);"
-- SQL Insert to add a new node.
sql_insert_node: STRING = "INSERT INTO nodes (revision, type, title, summary, content, publish, created, changed, author) VALUES (1, :type, :title, :summary, :content, :publish, :created, :changed, :author);"
-- SQL Insert to add a new node.
SQL_Update_node : STRING = "update nodes SET title=:title, summary=:summary, content=:content, publish=:publish, changed=:changed, version = version + 1, author=:author where nid=:nid;"
-- SQL node.
sql_update_node : STRING = "UPDATE nodes SET revision = revision + 1, type=:type, title=:title, summary=:summary, content=:content, publish=:publish, changed=:changed, revision = revision + 1, author=:author WHERE nid=:nid;"
-- SQL node.
SQL_Delete_node: STRING = "delete from nodes where nid=:nid;"
sql_delete_node: STRING = "DELETE FROM nodes WHERE nid=:nid;"
Sql_update_node_author: STRING = "update nodes SET author=:author where nid=:nid;"
-- sql_update_node_author: STRING = "UPDATE nodes SET author=:author WHERE nid=:nid;"
SQL_Update_node_title: STRING ="update nodes SET title=:title, changed=:changed, version = version + 1 where nid=:nid;"
-- SQL update node title.
-- sql_update_node_title: STRING ="UPDATE nodes SET title=:title, changed=:changed, revision = revision + 1 WHERE nid=:nid;"
-- -- SQL update node title.
SQL_Update_node_summary: STRING ="update nodes SET summary=:summary, changed=:changed, version = version + 1 where nid=:nid;"
-- SQL update node summary.
-- sql_update_node_summary: STRING ="UPDATE nodes SET summary=:summary, changed=:changed, revision = revision + 1 WHERE nid=:nid;"
-- -- SQL update node summary.
SQL_Update_node_content: STRING ="update nodes SET content=:content, changed=:changed, version = version + 1 where nid=:nid;"
-- SQL node content.
-- sql_update_node_content: STRING ="UPDATE nodes SET content=:content, changed=:changed, revision = revision + 1 WHERE nid=:nid;"
-- -- SQL node content.
Sql_last_insert_node_id: STRING = "SELECT MAX(nid) from nodes;"
sql_last_insert_node_id: STRING = "SELECT MAX(nid) FROM nodes;"
feature {NONE} -- Sql Queries: USER_ROLES collaborators, author
Select_user_author: STRING = "SELECT * FROM Nodes INNER JOIN users ON nodes.author=users.uid and users.uid = :uid;"
Select_user_author: STRING = "SELECT uid, name, password, salt, email, status, created, signed FROM Nodes INNER JOIN users ON nodes.author=users.uid AND users.uid = :uid;"
Select_node_author: STRING = "SELECT * FROM Users INNER JOIN nodes ON nodes.author=users.uid and nodes.nid =:nid;"
Select_node_author: STRING = "SELECT nid, revision, type, title, summary, content, author, publish, created, changed FROM users INNER JOIN nodes ON nodes.author=users.uid AND nodes.nid =:nid;"
feature {NONE} -- Implementation
fetch_node: CMS_NODE
fetch_node: detachable CMS_PARTIAL_NODE
do
create Result.make ("", "", "")
if attached sql_read_integer_64 (1) as l_id then
Result.set_id (l_id)
end
if attached sql_read_string_32 (4) as l_title then
Result.set_title (l_title)
end
if attached sql_read_string_32 (5) as l_summary then
Result.set_summary (l_summary)
end
if attached sql_read_string (6) as l_content then
Result.set_content (l_content)
end
if attached sql_read_date_time (8) as l_publication_date then
Result.set_publication_date (l_publication_date)
end
if attached sql_read_date_time (9) as l_creation_date then
Result.set_creation_date (l_creation_date)
end
if attached sql_read_date_time (10) as l_modif_date then
Result.set_modification_date (l_modif_date)
end
if attached sql_read_integer_64 (7) as l_author_id then
-- access to API ...
if attached sql_read_string (3) as l_type then
create Result.make_empty (l_type)
if attached sql_read_integer_64 (1) as l_id then
Result.set_id (l_id)
end
if attached sql_read_integer_64 (2) as l_revision then
Result.set_revision (l_revision)
end
if attached sql_read_string_32 (4) as l_title then
Result.set_title (l_title)
end
if attached sql_read_string_32 (5) as l_summary then
Result.set_summary (l_summary)
end
if attached sql_read_string (6) as l_content then
Result.set_content (l_content)
end
if attached sql_read_date_time (8) as l_publication_date then
Result.set_publication_date (l_publication_date)
end
if attached sql_read_date_time (9) as l_creation_date then
Result.set_creation_date (l_creation_date)
end
if attached sql_read_date_time (10) as l_modif_date then
Result.set_modification_date (l_modif_date)
end
if attached sql_read_integer_64 (7) as l_author_id then
Result.set_author (create {CMS_PARTIAL_USER}.make_with_id (l_author_id))
end
end
end

View File

@@ -0,0 +1,111 @@
note
description: "Storage extension for Page nodes."
date: "$Date$"
revision: "$Revision$"
class
CMS_NODE_STORAGE_SQL_PAGE_EXTENSION
inherit
CMS_NODE_STORAGE_EXTENSION [CMS_PAGE]
CMS_PROXY_STORAGE_SQL
rename
sql_storage as node_storage
redefine
node_storage
end
SHARED_LOGGER
create
make
feature {NONE} -- Initialization
node_storage: CMS_NODE_STORAGE_SQL
-- <Precursor>
feature -- Access
content_type: STRING
once
Result := {CMS_PAGE_CONTENT_TYPE}.name
end
feature -- Persistence
store (a_node: CMS_PAGE)
local
l_parameters: STRING_TABLE [ANY]
l_new_parent_id, l_previous_parent_id: INTEGER_64
l_update: BOOLEAN
do
error_handler.reset
write_information_log (generator + ".store_page_data")
create l_parameters.make (2)
l_parameters.put (a_node.id, "nid")
l_parameters.put (a_node.revision, "revision")
sql_query (sql_select_page_data, l_parameters)
if has_error then
if sql_rows_count = 1 then
l_previous_parent_id := sql_read_integer_64 (3)
l_update := True
end
if attached a_node.parent as l_parent then
l_new_parent_id := l_parent.id
else
l_new_parent_id := 0
end
l_parameters.put (l_new_parent_id, "parent")
if l_update and l_new_parent_id /= l_previous_parent_id then
sql_change (sql_update_page_data, l_parameters)
elseif l_new_parent_id > 0 then
sql_change (sql_insert_page_data, l_parameters)
else
-- no page data, means everything is empty.
end
end
end
load (a_node: CMS_PAGE)
local
l_parameters: STRING_TABLE [ANY]
n: INTEGER
ct: CMS_PAGE_CONTENT_TYPE
do
error_handler.reset
write_information_log (generator + ".fill_page")
create l_parameters.make (2)
l_parameters.put (a_node.id, "nid")
l_parameters.put (a_node.revision, "revision")
sql_query (sql_select_page_data, l_parameters)
if not has_error then
n := sql_rows_count
if n = 1 then
-- nid, revision, parent
if
attached sql_read_integer_64 (3) as l_parent_id and then
l_parent_id /= a_node.id and then
attached node_storage.node_by_id (l_parent_id) as l_parent
then
create ct
a_node.set_parent (ct.new_node (l_parent))
else
write_debug_log ("Invalid parent node id!")
end
else
check unique_data: n = 0 end
end
end
end
feature -- SQL
sql_select_page_data: STRING = "SELECT nid, revision, parent FROM page_nodes WHERE nid =:nid AND revision=:revision;"
sql_insert_page_data: STRING = "INSERT INTO page_nodes (nid, revision, parent) VALUES (:nid, :revision, :parent);"
sql_update_page_data: STRING = "UPDATE page_nodes SET nid=:nid, revision=:revision, parent=:parent WHERE nid=:nid AND revision=:revision;"
end

View File

@@ -90,29 +90,29 @@ feature -- Change: user
feature -- Access: roles and permissions
user_has_permission (u: detachable CMS_USER; s: detachable READABLE_STRING_8): BOOLEAN
-- Anonymous or user `u' has permission for `s' ?
--| `s' could be "create page",
do
-- if s = Void then
-- Result := True
-- elseif u = Void then
---- Result := user_role_has_permission (anonymous_user_role, s)
-- else
-- Result := user_role_has_permission (authenticated_user_role, s)
-- if not Result and attached u.roles as l_roles then
-- across
-- l_roles as r
-- until
-- Result
-- loop
-- if attached user_role_by_id (r.item) as ur then
-- Result := user_role_has_permission (ur, s)
-- end
-- end
-- end
-- end
end
-- user_has_permission (u: detachable CMS_USER; s: detachable READABLE_STRING_8): BOOLEAN
-- -- Anonymous or user `u' has permission for `s' ?
-- --| `s' could be "create page",
-- do
---- if s = Void then
---- Result := True
---- elseif u = Void then
------ Result := user_role_has_permission (anonymous_user_role, s)
---- else
---- Result := user_role_has_permission (authenticated_user_role, s)
---- if not Result and attached u.roles as l_roles then
---- across
---- l_roles as r
---- until
---- Result
---- loop
---- if attached user_role_by_id (r.item) as ur then
---- Result := user_role_has_permission (ur, s)
---- end
---- end
---- end
---- end
-- end
user_role_has_permission (a_role: CMS_USER_ROLE; s: READABLE_STRING_8): BOOLEAN
do
@@ -124,6 +124,12 @@ feature -- Access: roles and permissions
deferred
end
user_roles_for (a_user: CMS_USER): LIST [CMS_USER_ROLE]
-- User roles for user `a_user'.
-- Note: anonymous and authenticated roles are not included.
deferred
end
user_roles: LIST [CMS_USER_ROLE]
-- Possible list of user roles.
deferred

View File

@@ -208,24 +208,240 @@ feature -- Change: user
feature -- Access: roles and permissions
user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
local
l_parameters: STRING_TABLE [ANY]
do
to_implement (generator + ".user_role_by_id")
error_handler.reset
write_information_log (generator + ".user_role_by_id")
create l_parameters.make (1)
l_parameters.put (a_id, "rid")
sql_query (select_user_role_by_id, l_parameters)
if sql_rows_count = 1 then
Result := fetch_user_role
if Result /= Void and not has_error then
fill_user_role (Result)
end
else
check no_more_than_one: sql_rows_count = 0 end
end
end
user_roles_for (a_user: CMS_USER): LIST [CMS_USER_ROLE]
local
l_parameters: STRING_TABLE [ANY]
do
error_handler.reset
write_information_log (generator + ".user_roles_for")
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
from
create l_parameters.make (1)
l_parameters.put (a_user.id, "uid")
sql_query (select_user_roles_by_user_id, l_parameters)
sql_start
until
sql_after
loop
if attached fetch_user_role as l_role then
Result.force (l_role)
end
sql_forth
end
if not has_error then
across Result as ic loop
fill_user_role (ic.item)
end
end
end
user_roles: LIST [CMS_USER_ROLE]
local
l_role: detachable CMS_USER_ROLE
do
to_implement (generator + ".user_roles")
create {ARRAYED_LIST[CMS_USER_ROLE]} Result.make (0)
error_handler.reset
write_information_log (generator + ".user_roles")
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
from
sql_query (select_user_roles, Void)
sql_start
until
sql_after
loop
l_role := fetch_user_role
if l_role /= Void then
Result.force (l_role)
end
sql_forth
end
if not has_error then
across Result as ic loop
fill_user_role (ic.item)
end
end
end
fill_user_role (a_role: CMS_USER_ROLE)
require
a_role_has_id: a_role.has_id
do
if attached role_permissions_by_id (a_role.id) as l_permissions then
across
l_permissions as p_ic
loop
a_role.add_permission (p_ic.item)
end
end
end
role_permissions_by_id (a_role_id: INTEGER_32): LIST [READABLE_STRING_8]
local
l_parameters: STRING_TABLE [ANY]
do
error_handler.reset
write_information_log (generator + ".role_permissions_by_id")
create {ARRAYED_LIST [READABLE_STRING_8]} Result.make (0)
from
create l_parameters.make (1)
l_parameters.put (a_role_id, "rid")
sql_query (select_role_permissions_by_role_id, l_parameters)
sql_start
until
sql_after
loop
if attached sql_read_string (1) as l_permission then
Result.force (l_permission)
end
-- if attached sql_read_string_32 (2) as l_module then
-- end
sql_forth
end
end
feature -- Change: roles and permissions
save_user_role (a_user_role: CMS_USER_ROLE)
local
l_parameters: STRING_TABLE [detachable ANY]
l_existing_role: detachable CMS_USER_ROLE
l_permissions: detachable LIST [READABLE_STRING_8]
p: READABLE_STRING_8
l_found: BOOLEAN
do
to_implement (generator + ".save_user_role")
error_handler.reset
write_information_log (generator + ".save_user_role")
if a_user_role.has_id then
l_existing_role := user_role_by_id (a_user_role.id)
check l_existing_role /= Void and then l_existing_role.id = a_user_role.id end
if
l_existing_role /= Void and then
l_existing_role.name.same_string (a_user_role.name)
then
-- No update needed
else
create l_parameters.make (2)
l_parameters.put (a_user_role.id, "rid")
l_parameters.put (a_user_role.name, "name")
sql_change (sql_update_user_role, l_parameters)
end
if not a_user_role.permissions.is_empty then
-- FIXME: check if this is non set permissions,or none ...
if l_existing_role /= Void then
l_permissions := l_existing_role.permissions
fill_user_role (l_existing_role)
end
if l_permissions = Void or else l_permissions.is_empty then
l_permissions := role_permissions_by_id (a_user_role.id)
end
across
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
if l_found then
-- Already there, skip
else
-- Add permission
set_permission_for_role_id (p, a_user_role.id)
end
end
-- Remove other
across
l_permissions as ic
loop
unset_permission_for_role_id (ic.item, a_user_role.id)
end
end
else
create l_parameters.make (1)
l_parameters.put (a_user_role.name, "name")
sql_change (sql_insert_user_role, l_parameters)
if not error_handler.has_error then
a_user_role.set_id (last_inserted_user_role_id)
across
a_user_role.permissions as ic
loop
set_permission_for_role_id (ic.item, a_user_role.id)
end
end
end
end
feature {NONE} -- Implementation
set_permission_for_role_id (a_permission: READABLE_STRING_8; a_role_id: INTEGER)
require
a_role_id > 0
not a_permission.is_whitespace
local
l_parameters: STRING_TABLE [detachable ANY]
do
create l_parameters.make (3)
l_parameters.put (a_role_id, "rid")
l_parameters.put (a_permission, "permission")
l_parameters.put (Void, "module") -- FIXME: unsupported for now!
sql_change (sql_insert_user_role_permission, l_parameters)
end
unset_permission_for_role_id (a_permission: READABLE_STRING_8; a_role_id: INTEGER)
require
a_role_id > 0
not a_permission.is_whitespace
local
l_parameters: STRING_TABLE [detachable ANY]
do
create l_parameters.make (2)
l_parameters.put (a_role_id, "rid")
l_parameters.put (a_permission, "permission")
sql_change (sql_delete_user_role_permission, l_parameters)
end
last_inserted_user_role_id: INTEGER_32
-- Last inserted user role id.
do
error_handler.reset
write_information_log (generator + ".last_inserted_user_role_id")
sql_query (Sql_last_insert_user_role_id, Void)
if sql_rows_count = 1 then
Result := sql_read_integer_32 (1)
end
end
feature {NONE} -- Implementation: User
user_salt (a_username: READABLE_STRING_32): detachable READABLE_STRING_8
-- User salt for the given user `a_username', if any.
@@ -289,32 +505,83 @@ feature {NONE} -- Implementation
end
end
feature {NONE} -- Implementation: User role
fetch_user_role: detachable CMS_USER_ROLE
local
l_id: INTEGER_32
l_name: detachable READABLE_STRING_32
do
if attached sql_read_integer_32 (1) as rid then
l_id := rid
end
if attached sql_read_string_32 (2) as s and then not s.is_whitespace then
l_name := s
end
if l_name /= Void then
create Result.make (l_name)
if l_id > 0 then
Result.set_id (l_id)
end
elseif l_id > 0 then
create Result.make_with_id (l_id)
end
end
feature {NONE} -- Sql Queries: USER
Select_users_count: STRING = "select count(*) from Users;"
Select_users_count: STRING = "SELECT count(*) FROM Users;"
-- Number of users.
Sql_last_insert_user_id: STRING = "SELECT MAX(uid) from Users;"
Sql_last_insert_user_id: STRING = "SELECT MAX(uid) FROM Users;"
Select_users: STRING = "select * from Users;"
Select_users: STRING = "SELECT * FROM Users;"
-- List of users.
Select_user_by_id: STRING = "select * from Users where uid =:uid;"
Select_user_by_id: STRING = "SELECT * FROM Users WHERE uid =:uid;"
-- Retrieve user by id if exists.
Select_user_by_name: STRING = "select * from Users where name =:name;"
Select_user_by_name: STRING = "SELECT * FROM Users WHERE name =:name;"
-- Retrieve user by name if exists.
Select_user_by_email: STRING = "select * from Users where email =:email;"
Select_user_by_email: STRING = "SELECT * FROM Users WHERE email =:email;"
-- Retrieve user by email if exists.
Select_salt_by_username: STRING = "select salt from Users where name =:name;"
Select_salt_by_username: STRING = "SELECT salt FROM Users WHERE name =:name;"
-- Retrieve salt by username if exists.
Sql_Insert_user: STRING = "insert into users (name, password, salt, email, created) values (:name, :password, :salt, :email, :created);"
sql_insert_user: STRING = "INSERT INTO users (name, password, salt, email, created) VALUES (:name, :password, :salt, :email, :created);"
-- SQL Insert to add a new node.
sql_update_user: STRING = "update users SET name=:name, password=:password, salt=:salt, email=:email WHERE uid=:uid;"
sql_update_user: STRING = "UPDATE users SET name=:name, password=:password, salt=:salt, email=:email WHERE uid=:uid;"
feature {NONE} -- Sql Queries: USER ROLE
sql_last_insert_user_role_id: STRING = "SELECT MAX(rid) FROM roles;"
select_user_roles: STRING = "SELECT rid, name FROM roles;"
-- List of user roles.
sql_insert_user_role: STRING = "INSERT INTO roles (name) VALUES (:name);"
-- SQL Insert to add a new user role with name :name.
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;"
-- List of user roles for user id :uid.
select_user_role_by_id: STRING = "SELECT rid, name FROM roles WHERE rid=:rid;"
-- User role for role id :rid;
sql_insert_user_role_permission: STRING = "INSERT INTO role_permissions (rid, permission, module) VALUES (:rid, :permission, :module);"
-- SQL Insert a new permission :permission for user role :rid.
sql_delete_user_role_permission: STRING = "DELETE FROM role_permissions WHERE rid=:rid AND permission=:permission;"
-- SQL Delete permission :permission from user role :rid.
select_role_permissions_by_role_id: STRING = "SELECT permission, module FROM role_permissions WHERE rid=:rid;"
-- User role permissions for role id :rid;
end