/EIFGENs$
diff --git a/library/persistence/implementation/sqlite/src/cms_node_storage_sqlite.e b/library/persistence/implementation/sqlite/src/cms_node_storage_sqlite.e
new file mode 100644
index 0000000..6cafa70
--- /dev/null
+++ b/library/persistence/implementation/sqlite/src/cms_node_storage_sqlite.e
@@ -0,0 +1,14 @@
+note
+ description: "Summary description for {CMS_NODE_STORAGE_SQLITE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_NODE_STORAGE_SQLITE
+
+inherit
+ CMS_NODE_STORAGE_SQL
+
+
+end
diff --git a/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e b/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e
index f463110..1dacee9 100644
--- a/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e
+++ b/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e
@@ -7,8 +7,12 @@ class
CMS_STORAGE_SQLITE
inherit
-
CMS_STORAGE
+
+ CMS_USER_STORAGE_SQLITE
+
+ CMS_NODE_STORAGE_SQLITE
+
REFACTORING_HELPER
create
@@ -21,229 +25,77 @@ feature {NONE} -- Initialization
require
is_connected: a_connection.is_connected
do
- log.write_information (generator+".make_with_database is database connected? "+ a_connection.is_connected.out )
- create node_provider.make (a_connection)
- create user_provider.make (a_connection)
+ connection := a_connection
+ log.write_information (generator + ".make_with_database is database connected? "+ a_connection.is_connected.out )
+
+ create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
+
create error_handler.make
end
+ db_handler: DATABASE_HANDLER
+
+ connection: DATABASE_CONNECTION
+ -- Current database connection.
feature -- Access: user
- has_user: BOOLEAN
- -- Has any user?
+ sql_post_execution
+ -- Post database execution.
do
- Result := user_provider.has_user
-
- end
-
-
- all_users: LIST [CMS_USER]
- do
- to_implement("Not implemented!!!")
- create {ARRAYED_LIST[CMS_USER]} Result.make (0)
- end
-
- user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
- do
- Result := user_provider.user (a_id)
-
- end
-
- user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
- do
- Result := user_provider.user_by_name (a_name)
-
- end
-
- user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
- do
- Result := user_provider.user_by_email (a_email)
-
- end
-
- is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
- local
- l_security: SECURITY_PROVIDER
- do
- if attached user_provider.user_salt (l_auth_login) as l_hash then
- if attached user_provider.user_by_name (l_auth_login) as l_user then
- create l_security
- if
- attached l_user.password as l_password and then
- l_security.password_hash (l_auth_password, l_hash).is_case_insensitive_equal (l_password)
- then
- Result := True
- else
- log.write_information (generator + ".login_valid User: wrong username or password" )
- end
- else
- log.write_information (generator + ".login_valid User:" + l_auth_login + "does not exist" )
- end
+-- error_handler.add_synchronization (db_handler.database_error_handler)
+ if error_handler.has_error then
+ log.write_critical (generator + ".post_execution " + error_handler.as_string_representation)
end
-
end
-feature -- Change: user
-
- save_user (a_user: CMS_USER)
- -- Add a new user `a_user'.
+ sql_begin_transaction
do
- if
- attached a_user.password as l_password and then
- attached a_user.email as l_email
- then
- user_provider.new_user (a_user.name, l_password, l_email)
+ connection.begin_transaction
+ end
+
+ sql_commit_transaction
+ do
+ connection.commit
+ end
+
+ sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+ do
+ db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, Void))
+ db_handler.execute_query
+ end
+
+ sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+ do
+ db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, Void))
+ db_handler.execute_change
+ end
+
+ sql_rows_count: INTEGER
+ -- Number of rows for last sql execution.
+ do
+ Result := db_handler.count
+ end
+
+ sql_after: BOOLEAN
+ -- Are there no more items to iterate over?
+ do
+ Result := db_handler.after
+ end
+
+ sql_forth
+ -- Fetch next row from last sql execution, if any.
+ do
+ db_handler.forth
+ end
+
+ sql_item (a_index: INTEGER): detachable ANY
+ do
+ if attached {DB_TUPLE} db_handler.item as l_item and then l_item.count >= a_index then
+ Result := l_item.item (a_index)
else
- -- set error
+ check has_item_at_index: False end
end
end
-feature -- User Nodes
-
- user_collaborator_nodes (a_id: like {CMS_USER}.id): LIST[CMS_NODE]
- -- Possible list of nodes where the user identified by `a_id', is a collaborator.
- do
- create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
- to_implement ("Not implemented")
- end
-
- user_author_nodes (a_id: like {CMS_USER}.id): LIST[CMS_NODE]
- -- Possible list of nodes where the user identified by `a_id', is the author.
- do
- create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
- to_implement ("Not implemented")
- end
-
-feature -- Users roles and permissions
-
- user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
- -- User role by id `a_id', if any.
- do
- to_implement ("Not implemented")
- end
-
- user_roles: LIST [CMS_USER_ROLE]
- -- Possible list of user roles.
- do
- create {ARRAYED_LIST[CMS_USER_ROLE]} Result.make (0)
- to_implement ("Not implemented")
- end
-
-feature -- Change: roles and permissions
-
- save_user_role (a_user_role: CMS_USER_ROLE)
- -- Save user role `a_user_role'
- do
- to_implement ("Not implemented")
- end
-
-
-feature -- Access: node
-
- nodes: LIST[CMS_NODE]
- -- List of nodes.
- do
- create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
- across node_provider.nodes as c loop
- Result.force (c.item)
- end
-
- end
-
- recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
- -- List of the `a_count' most recent nodes, starting from `a_lower'.
- do
- create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
- across node_provider.recent_nodes (a_lower,a_count) as c loop
- Result.force (c.item)
- end
-
- end
-
- node (a_id: INTEGER_64): detachable CMS_NODE
- --
- do
- Result := node_provider.node (a_id)
-
- end
-
-
-feature -- Node
-
- save_node (a_node: CMS_NODE)
- -- Add a new node
- do
- node_provider.new_node (a_node)
-
- end
-
- delete_node (a_id: INTEGER_64)
- do
- node_provider.delete_node (a_id)
-
- end
-
- update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE)
- do
- node_provider.update_node (a_node)
-
- end
-
- update_node_title (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
- do
- node_provider.update_node_title (a_id, a_title)
-
- end
-
- update_node_summary (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
- do
- node_provider.update_node_summary (a_id, a_summary)
-
- end
-
- update_node_content (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
- do
- node_provider.update_node_content (a_id, a_content)
-
- end
-
-
- node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
- -- Node's author. if any.
- do
- to_implement ("Not implemented")
- end
-
- node_collaborators (a_id: like {CMS_NODE}.id): LIST [CMS_USER]
- -- Possible list of node's collaborator.
- do
- create {ARRAYED_LIST[CMS_USER]} Result.make (0)
- to_implement ("Not implemented")
- end
-
-
-feature -- User
-
- new_user (a_user: CMS_USER)
- -- Add a new user `a_user'.
- do
- if
- attached a_user.password as l_password and then
- attached a_user.email as l_email
- then
- user_provider.new_user (a_user.name, l_password, l_email)
- else
- -- set error
- end
- end
-
-feature {NONE} -- Implementation
-
- node_provider: NODE_DATA_PROVIDER
- -- Node Data provider.
-
- user_provider: USER_DATA_PROVIDER
- -- User Data provider.
-
end
diff --git a/library/persistence/implementation/sqlite/src/cms_storage_sqlite_builder.e b/library/persistence/implementation/sqlite/src/cms_storage_sqlite_builder.e
new file mode 100644
index 0000000..2ecd752
--- /dev/null
+++ b/library/persistence/implementation/sqlite/src/cms_storage_sqlite_builder.e
@@ -0,0 +1,43 @@
+note
+ description: "[
+ Objects that ...
+ ]"
+ author: "$Author$"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_STORAGE_SQLITE_BUILDER
+
+inherit
+ CMS_STORAGE_BUILDER
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ -- Initialize `Current'.
+ do
+ end
+
+feature -- Factory
+
+ storage (a_setup: CMS_SETUP): detachable CMS_STORAGE_SQLITE
+ local
+ s: STRING
+ do
+ if attached (create {APPLICATION_JSON_CONFIGURATION_HELPER}).new_database_configuration (a_setup.layout.application_config_path) as l_database_config then
+ s := "Driver=SQLite3 ODBC Driver;Database="
+ if attached l_database_config.database_name as db_name then
+ s.append (db_name)
+ end
+ s.append (";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;")
+ create Result.make (create {DATABASE_CONNECTION_ODBC}.login_with_connection_string (s))
+ --create Result.make (create {DATABASE_CONNECTION_ODBC}.login_with_connection_string (l_database_config.connection_string))
+ end
+ end
+
+
+end
diff --git a/library/persistence/implementation/sqlite/src/cms_user_storage_sqlite.e b/library/persistence/implementation/sqlite/src/cms_user_storage_sqlite.e
new file mode 100644
index 0000000..42f525e
--- /dev/null
+++ b/library/persistence/implementation/sqlite/src/cms_user_storage_sqlite.e
@@ -0,0 +1,14 @@
+note
+ description: "Summary description for {CMS_USER_STORAGE_SQLITE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_USER_STORAGE_SQLITE
+
+inherit
+ CMS_USER_STORAGE_SQL
+
+
+end
diff --git a/library/persistence/implementation/sqlite/src/provider/node_data_provider.e b/library/persistence/implementation/sqlite/src/provider/node_data_provider.e
deleted file mode 100644
index 25c4606..0000000
--- a/library/persistence/implementation/sqlite/src/provider/node_data_provider.e
+++ /dev/null
@@ -1,275 +0,0 @@
-note
- description: "Database access for node uses cases."
- date: "$Date: 2014-11-13 12:23:47 -0300 (ju., 13 nov. 2014) $"
- revision: "$Revision: 96085 $"
-
-class
- NODE_DATA_PROVIDER
-
-inherit
-
- PARAMETER_NAME_HELPER
-
- SHARED_ERROR
-
- REFACTORING_HELPER
-
-create
- make
-
-feature -- Initialization
-
- make (a_connection: DATABASE_CONNECTION)
- -- Create a data provider.
- do
- create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
-
- end
-
- db_handler: DATABASE_HANDLER
- -- Db handler.
-
-feature -- Status Report
-
- is_successful: BOOLEAN
- -- Is the last execution sucessful?
- do
- Result := not db_handler.has_error
- end
-
-feature -- Access
-
- nodes: DATABASE_ITERATION_CURSOR [CMS_NODE]
- -- List of nodes.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".nodes")
- create l_parameters.make (0)
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_nodes, l_parameters))
- db_handler.execute_query
- create Result.make (db_handler, agent fetch_node)
-
- end
-
- recent_nodes (a_lower, a_rows: INTEGER): DATABASE_ITERATION_CURSOR [CMS_NODE]
- -- The most recent `a_rows'.
- local
- l_parameters: STRING_TABLE [ANY]
- l_query: STRING
- do
- log.write_information (generator + ".recent_nodes")
- create l_parameters.make (2)
- l_parameters.put (a_rows, "rows")
- create l_query.make_from_string (select_recent_nodes)
- l_query.replace_substring_all ("$offset", a_lower.out)
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (l_query, l_parameters))
- db_handler.execute_query
- create Result.make (db_handler, agent fetch_node)
-
- end
-
- node (a_id: INTEGER_64): detachable CMS_NODE
- -- Node for the given id `a_id', if any.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".node")
- create l_parameters.make (1)
- l_parameters.put (a_id,"id")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_node_by_id, l_parameters))
- db_handler.execute_query
- if db_handler.count = 1 then
- Result := fetch_node
- end
-
- end
-
- count: INTEGER
- -- Number of items nodes.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".count")
- create l_parameters.make (0)
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_count, l_parameters))
- db_handler.execute_query
- if db_handler.count = 1 then
- Result := db_handler.read_integer_32 (1)
- end
-
- end
-
-feature -- Basic operations
-
- new_node (a_node: CMS_NODE)
- -- Create a new node.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".new_node")
- create l_parameters.make (6)
- 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, "publication_date")
- l_parameters.put (a_node.creation_date, "creation_date")
- l_parameters.put (a_node.modification_date, "modification_date")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_insert_node, l_parameters))
- db_handler.execute_change
-
- end
-
- update_node_title (a_id: INTEGER_64; a_title: READABLE_STRING_32)
- -- Update node title for the corresponding the report with id `a_id'.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".update_node_title")
- create l_parameters.make (3)
- l_parameters.put (a_title, "title")
- l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
- l_parameters.put (a_id, "id")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_title, l_parameters))
- db_handler.execute_change
-
- end
-
- update_node_summary (a_id: INTEGER_64; a_summary: READABLE_STRING_32)
- -- Update node summary for the corresponding the report with id `a_id'.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".update_node_summary")
- create l_parameters.make (3)
- l_parameters.put (a_summary, "summary")
- l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
- l_parameters.put (a_id, "id")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_summary, l_parameters))
- db_handler.execute_change
-
- end
-
- update_node_content (a_id: INTEGER_64; a_content: READABLE_STRING_32)
- -- Update node content for the corresponding the report with id `a_id'.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".update_node_content")
- create l_parameters.make (3)
- l_parameters.put (a_content, "content")
- l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
- l_parameters.put (a_id, "id")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_content, l_parameters))
- db_handler.execute_change
-
- end
-
- update_node (a_node: CMS_NODE)
- -- Update node.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".update_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, "publication_date")
- l_parameters.put (a_node.creation_date, "creation_date")
- l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
- l_parameters.put (a_node.id, "id")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node, l_parameters))
- db_handler.execute_change
-
- end
-
- delete_node (a_id: INTEGER_64;)
- -- Delete node with id `a_id'.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".delete_node")
- create l_parameters.make (1)
- l_parameters.put (a_id, "id")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_delete_node, l_parameters))
- db_handler.execute_change
- end
-
-feature -- Connection
-
- connect
- -- Connect to the database.
- do
- if not db_handler.is_connected then
- db_handler.connect
- end
- end
-
- disconnect
- -- Disconnect to the database.
- do
- if db_handler.is_connected then
- db_handler.disconnect
- end
- end
-
-feature {NONE} -- Queries
-
- Select_count: STRING = "select count(*) from Nodes;"
-
- Select_nodes: STRING = "select * from Nodes;"
- -- SQL Query to retrieve all nodes.
-
- Select_node_by_id: STRING = "select * from Nodes where id =:id order by id desc, publication_date desc;"
-
- Select_recent_nodes: STRING = "select * from Nodes order by id desc, publication_date desc Limit $offset , :rows "
-
- SQL_Insert_node: STRING = "insert into nodes (title, summary, content, publication_date, creation_date, modification_date) values (:title, :summary, :content, :publication_date, :creation_date, :modification_date);"
- -- SQL Insert to add a new node.
-
- SQL_Update_node_title: STRING ="update nodes SET title=:title, modification_date=:modification_date where id=:id;"
- -- SQL update node title.
-
- SQL_Update_node_summary: STRING ="update nodes SET summary=:summary, modification_date=:modification_date where id=:id;"
- -- SQL update node summary.
-
- SQL_Update_node_content: STRING ="update nodes SET content=:content, modification_date=:modification_date where id=:id;"
- -- SQL node content.
-
- SQL_Update_node : STRING = "update nodes SET title=:title, summary=:summary, content=:content, publication_date=:publication_date, creation_date=:creation_date, modification_date=:modification_date where id=:id;"
- -- SQL node.
-
- SQL_Delete_node: STRING = "delete from nodes where id=:id;"
-
-
-feature -- New Object
-
- fetch_node: CMS_NODE
- do
- create Result.make ("", "", "")
- if attached db_handler.read_integer_32 (1) as l_id then
- Result.set_id (l_id)
- end
- if attached db_handler.read_date_time (2) as l_pd then
- Result.set_publication_date (l_pd)
- end
- if attached db_handler.read_date_time (3) as l_cd then
- Result.set_creation_date (l_cd)
- end
- if attached db_handler.read_date_time (4) as l_md then
- Result.set_modification_date (l_md)
- end
- if attached db_handler.read_string (5) as l_t then
- Result.set_title (l_t)
- end
- if attached db_handler.read_string (6) as l_s then
- Result.set_summary (l_s)
- end
- if attached db_handler.read_string (7) as l_c then
- Result.set_content (l_c)
- end
- end
-
-
-end
diff --git a/library/persistence/implementation/sqlite/src/provider/user_data_provider.e b/library/persistence/implementation/sqlite/src/provider/user_data_provider.e
deleted file mode 100644
index 60fd235..0000000
--- a/library/persistence/implementation/sqlite/src/provider/user_data_provider.e
+++ /dev/null
@@ -1,193 +0,0 @@
-note
- description: "Summary description for {USER_DATA_PROVIDER}."
- date: "$Date: 2014-11-13 12:23:47 -0300 (ju., 13 nov. 2014) $"
- revision: "$Revision: 96085 $"
-
-class
- USER_DATA_PROVIDER
-
-inherit
-
- PARAMETER_NAME_HELPER
-
- SHARED_ERROR
-
- REFACTORING_HELPER
-
-create
- make
-
-feature -- Initialization
-
- make (a_connection: DATABASE_CONNECTION)
- -- Create a data provider.
- do
- create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
-
- end
-
- db_handler: DATABASE_HANDLER
- -- Db handler.
-
-feature -- Status Report
-
- is_successful: BOOLEAN
- -- Is the last execution sucessful?
- do
- Result := not db_handler.has_error
- end
-
- has_user: BOOLEAN
- -- Has any user?
- do
- Result := count > 0
- end
-
-feature -- Basic Operations
-
- new_user (a_user_name: READABLE_STRING_32; a_password: READABLE_STRING_32; a_email: READABLE_STRING_32)
- -- Create a new node.
- local
- l_parameters: STRING_TABLE [detachable ANY]
- l_password_salt, l_password_hash: STRING
- l_security: SECURITY_PROVIDER
- do
- create l_security
- l_password_salt := l_security.salt
- l_password_hash := l_security.password_hash (a_password, l_password_salt)
-
- log.write_information (generator + ".new_user")
- create l_parameters.make (4)
- l_parameters.put (a_user_name,"username")
- l_parameters.put (l_password_hash,"password")
- l_parameters.put (l_password_salt,"salt")
- l_parameters.put (a_email,"email")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_insert_user, l_parameters))
- db_handler.execute_change
-
- end
-
- user (a_id: INTEGER_64): detachable CMS_USER
- -- User for the given id `a_id', if any.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".user")
- create l_parameters.make (1)
- l_parameters.put (a_id,"id")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_user_by_id, l_parameters))
- db_handler.execute_query
- if db_handler.count = 1 then
- Result := fetch_user
- end
-
- end
-
- user_by_name (a_name: READABLE_STRING_32): detachable CMS_USER
- -- User for the given name `a_name', if any.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".user_by_name")
- create l_parameters.make (1)
- l_parameters.put (a_name,"name")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_user_by_name, l_parameters))
- db_handler.execute_query
- if db_handler.count = 1 then
- Result := fetch_user
- end
-
- end
-
-
- user_by_email (a_email: detachable READABLE_STRING_32): detachable CMS_USER
- -- User for the given email `a_email', if any.
- local
- l_parameters: STRING_TABLE [detachable ANY]
- do
- log.write_information (generator + ".user_by_email")
- create l_parameters.make (1)
- l_parameters.put (a_email,"email")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_user_by_email, l_parameters))
- db_handler.execute_query
- if db_handler.count = 1 then
- Result := fetch_user
- end
-
- end
-
- user_salt (a_username: READABLE_STRING_32): detachable READABLE_STRING_32
- -- User salt for the given user `a_username', if any.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".user_salt")
- create l_parameters.make (1)
- l_parameters.put (a_username,"name")
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_salt_by_username, l_parameters))
- db_handler.execute_query
- if db_handler.count = 1 then
- if attached db_handler.read_string (1) as l_salt then
- Result := l_salt.as_string_32
- end
- end
-
- end
-
- count: INTEGER
- -- Number of items users.
- local
- l_parameters: STRING_TABLE [ANY]
- do
- log.write_information (generator + ".count")
- create l_parameters.make (0)
- db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_count, l_parameters))
- db_handler.execute_query
- if db_handler.count = 1 then
- Result := db_handler.read_integer_32 (1)
- end
-
- end
-
-feature -- New Object
-
- fetch_user: CMS_USER
- do
- create Result.make ("")
- if attached db_handler.read_integer_32 (1) as l_id then
- Result.set_id (l_id)
- end
- if attached db_handler.read_string (2) as l_u then
- Result.set_name (l_u)
- end
- if attached db_handler.read_string (3) as l_p then
- Result.set_password (l_p)
- end
- if attached db_handler.read_string (5) as l_e then
- Result.set_email (l_e)
- end
- end
-
-feature -- Sql Queries
-
- Select_count: STRING = "select count(*) from Users;"
- -- Number of users.
-
- Select_user_by_id: STRING = "select * from Users where id =:id;"
- -- Retrieve user by id if exists.
-
- Select_user_by_name: STRING = "select * from Users where username =:name;"
- -- Retrieve user by name if exists.
-
- 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 username =:name;"
- -- Retrieve salt by username if exists.
-
- SQL_Insert_user: STRING = "insert into users (username, password, salt, email) values (:username, :password, :salt, :email);"
- -- SQL Insert to add a new node.
-
-
-
-end
diff --git a/library/persistence/implementation/sqlite/tests/storage/storage_test_set.e b/library/persistence/implementation/sqlite/tests/storage/storage_test_set.e
index 4d893ed..1475460 100644
--- a/library/persistence/implementation/sqlite/tests/storage/storage_test_set.e
+++ b/library/persistence/implementation/sqlite/tests/storage/storage_test_set.e
@@ -216,6 +216,7 @@ feature -- Test routines
across 1 |..| 10 as c loop
storage.save_node (custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out))
end
+ assert ("has nodes", storage.nodes.count > 5)
assert ("Node id: 10", attached storage.node (10) as l_node and then l_node.title ~ "Title_10" )
end
diff --git a/library/persistence/implementation/sqlite/tests/tests-safe.ecf b/library/persistence/implementation/sqlite/tests/tests-safe.ecf
index a905aec..e06085e 100644
--- a/library/persistence/implementation/sqlite/tests/tests-safe.ecf
+++ b/library/persistence/implementation/sqlite/tests/tests-safe.ecf
@@ -7,6 +7,7 @@
+
diff --git a/library/persistence/implementation/sqlite/tests/util/abstract_db_test.e b/library/persistence/implementation/sqlite/tests/util/abstract_db_test.e
index 6ba5b1b..70b5fdc 100644
--- a/library/persistence/implementation/sqlite/tests/util/abstract_db_test.e
+++ b/library/persistence/implementation/sqlite/tests/util/abstract_db_test.e
@@ -12,8 +12,8 @@ feature -- Database connection
connection: DATABASE_CONNECTION_ODBC
-- odbc database connection
once
--- create Result.login_with_connection_string ("Driver=SQLite3 ODBC Driver;Database=PATH/SQLITE.FILE;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;")
- create Result.make_basic ("cms_dev")
+ create Result.login_with_connection_string ("Driver=SQLite3 ODBC Driver;Database=cms_lite.db;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;")
+-- create Result.make_basic ("cms_lite.db")
end
end
diff --git a/library/src/modules/node/node_module.e b/library/src/modules/node/node_module.e
index 8150e3e..3e85a4d 100644
--- a/library/src/modules/node/node_module.e
+++ b/library/src/modules/node/node_module.e
@@ -33,7 +33,6 @@ feature {NONE} -- Initialization
config := a_setup
end
-
config: CMS_SETUP
-- Node configuration.
@@ -159,10 +158,28 @@ feature -- Handler
do_get_nodes (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
local
r: CMS_RESPONSE
+ s: STRING
do
create {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE} r.make (req, res, a_api)
- r.set_main_content ("Sorry: listing the CMS nodes is not yet implemented.")
- r.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet implemented", Void), "highlighted")
+
+ a_api.new_node (create {CMS_NODE}.make ("This is a body", "summary this node", "Oh a node"))
+
+ create s.make_from_string ("Sorry: listing the CMS nodes is not yet implemented.
")
+ if attached a_api.nodes as lst then
+ across
+ lst as ic
+ loop
+ s.append ("")
+ s.append (a_api.html_encoded (ic.item.title))
+ s.append (" (")
+ s.append (ic.item.id.out)
+ s.append (")")
+ s.append ("%N")
+ end
+ end
+
+ r.set_main_content (s)
+ r.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet implemented
", Void), "highlighted")
r.execute
end
diff --git a/library/src/persistence/cms_storage.e b/library/src/persistence/cms_storage.e
index 234613d..309bfd2 100644
--- a/library/src/persistence/cms_storage.e
+++ b/library/src/persistence/cms_storage.e
@@ -3,13 +3,16 @@ note
description : "[
CMS interface to storage
]"
- date : "$Date$"
- revision : "$Revision$"
+ date: "$Date$"
+ revision: "$Revision$"
deferred class
CMS_STORAGE
inherit
+ CMS_USER_STORAGE
+
+ CMS_NODE_STORAGE
SHARED_LOGGER
@@ -24,224 +27,7 @@ feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
-feature -- Access: user
-
- has_user: BOOLEAN
- -- Has any user?
- deferred
- end
-
- all_users: LIST [CMS_USER]
- -- Possible list of users.
- deferred
- end
-
- user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
- -- User with id `a_id', if any.
- require
- a_id > 0
- deferred
- ensure
- same_id: Result /= Void implies Result.id = a_id
- password: Result /= Void implies Result.password /= Void
- end
-
- user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
- -- User with name `a_name', if any.
- require
- a_name /= Void and then not a_name.is_empty
- deferred
- ensure
- same_name: Result /= Void implies a_name ~ Result.name
- password: Result /= Void implies Result.password /= Void
- end
-
- user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
- -- User with name `a_email', if any.
- deferred
- ensure
- same_email: Result /= Void implies a_email ~ Result.email
- password: Result /= Void implies Result.password /= Void
- end
-
- is_valid_credential (a_u, a_p: READABLE_STRING_32): BOOLEAN
- -- Does account with username `a_username' and password `a_password' exist?
- deferred
- end
-
-feature -- User Nodes
-
- user_collaborator_nodes (a_id: like {CMS_USER}.id): LIST[CMS_NODE]
- -- Possible list of nodes where the user identified by `a_id', is a collaborator.
- require
- a_id > 0
- deferred
- end
-
- user_author_nodes (a_id: like {CMS_USER}.id): LIST[CMS_NODE]
- -- Possible list of nodes where the user identified by `a_id', is the author.
- require
- a_id > 0
- deferred
- end
-
-feature -- Change: user
-
- save_user (a_user: CMS_USER)
- -- Save user `a_user'.
- deferred
- end
-
-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_role_has_permission (a_role: CMS_USER_ROLE; s: READABLE_STRING_8): BOOLEAN
- do
- Result := a_role.has_permission (s)
- end
-
- user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
- -- User role by id `a_id', if any.
- deferred
- end
-
- user_roles: LIST [CMS_USER_ROLE]
- -- Possible list of user roles.
- deferred
- end
-
-feature -- Change: roles and permissions
-
- save_user_role (a_user_role: CMS_USER_ROLE)
- -- Save user role `a_user_role'
- deferred
- end
-
-feature -- Email
-
--- save_email (a_email: NOTIFICATION_EMAIL)
--- deferred
--- end
-
---feature -- Log
-
--- recent_logs (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_LOG]
--- deferred
--- end
-
--- log (a_id: like {CMS_LOG}.id): detachable CMS_LOG
--- require
--- a_id > 0
--- deferred
--- end
-
--- save_log (a_log: CMS_LOG)
--- deferred
--- end
-
-feature -- Access: Node
-
- recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
- -- List of recent `a_count' nodes with an offset of `lower'.
- deferred
- end
-
- node (a_id: INTEGER_64): detachable CMS_NODE
- -- Retrieve node by id `a_id', if any.
- require
- a_id > 0
- deferred
- end
-
- node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
- -- Node's author. if any.
- require
- valid_node: a_id >0
- deferred
- end
-
- node_collaborators (a_id: like {CMS_NODE}.id): LIST [CMS_USER]
- -- Possible list of node's collaborator.
- require
- valid_node: a_id > 0
- deferred
- end
-
-feature -- Change: Node
-
- save_node (a_node: CMS_NODE)
- -- Save node `a_node'.
- require
- valid_user: attached a_node.author as l_author and then l_author.id > 0
- deferred
- end
-
- delete_node (a_id: INTEGER_64)
- -- Remove node by id `a_id'.
- require
- valid_node_id: a_id > 0
- deferred
- end
-
- update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE)
- -- Update node content `a_node'.
- -- The user `a_id' is an existing or new collaborator.
- require
- valid_node_id: a_node.id > 0
- valid_user_id: a_id > 0
- deferred
- end
-
- update_node_title (a_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_id' is an existing or new collaborator.
- require
- valid_node_id: a_node_id > 0
- valid_user_id: a_id > 0
- deferred
- end
-
- update_node_summary (a_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_id' is an existing or new collaborator.
- require
- valid_id: a_node_id > 0
- deferred
- end
-
- update_node_content (a_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_id' is an existing or new collaborator.
- require
- valid_id: a_node_id > 0
- valid_user_id: a_id > 0
- deferred
- end
-
---feature -- Misc
+feature -- Misc
-- set_custom_value (a_name: READABLE_STRING_8; a_value: attached like custom_value; a_type: READABLE_STRING_8)
-- -- Save data `a_name:a_value' for type `a_type'
diff --git a/library/src/persistence/cms_storage_null.e b/library/src/persistence/cms_storage_null.e
index 89eb3df..4b0b83f 100644
--- a/library/src/persistence/cms_storage_null.e
+++ b/library/src/persistence/cms_storage_null.e
@@ -33,7 +33,7 @@ feature -- Access: user
do
end
- all_users: LIST [CMS_USER]
+ users: LIST [CMS_USER]
do
create {ARRAYED_LIST[CMS_USER]} Result.make (0)
end
diff --git a/library/src/persistence/cms_storage_sql.e b/library/src/persistence/cms_storage_sql.e
new file mode 100644
index 0000000..c9e9372
--- /dev/null
+++ b/library/src/persistence/cms_storage_sql.e
@@ -0,0 +1,153 @@
+note
+ description: "Summary description for {CMS_STORAGE_SQL}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_STORAGE_SQL
+
+feature -- Error handler
+
+ error_handler: ERROR_HANDLER
+ deferred
+ end
+
+feature -- Execution
+
+ sql_begin_transaction
+ deferred
+ end
+
+ sql_commit_transaction
+ deferred
+ end
+
+ sql_post_execution
+ -- Post database execution.
+ deferred
+ end
+
+feature -- Operation
+
+ sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+ deferred
+ end
+
+ sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+ deferred
+ end
+
+feature -- Access
+
+ sql_rows_count: INTEGER
+ -- Number of rows for last sql execution.
+ deferred
+ end
+
+ sql_after: BOOLEAN
+ -- Are there no more items to iterate over?
+ deferred
+ end
+
+ sql_forth
+ -- Fetch next row from last sql execution, if any.
+ deferred
+ end
+
+ sql_item (a_index: INTEGER): detachable ANY
+ deferred
+ end
+
+ sql_read_integer_64 (a_index: INTEGER): INTEGER_64
+ -- Retrieved value at `a_index' position in `item'.
+ local
+ l_item: like sql_item
+ do
+ l_item := sql_item (a_index)
+ if attached {INTEGER_64} l_item as i then
+ Result := i
+ elseif attached {INTEGER_64_REF} l_item as l_value then
+ Result := l_value.item
+ else
+ Result := sql_read_integer_32 (a_index).to_integer_64
+ end
+ end
+
+ sql_read_integer_32 (a_index: INTEGER): INTEGER_32
+ -- Retrieved value at `a_index' position in `item'.
+ local
+ l_item: like sql_item
+ do
+ l_item := sql_item (a_index)
+ if attached {INTEGER_32} l_item as i then
+ Result := i
+ elseif attached {INTEGER_32_REF} l_item as l_value then
+ Result := l_value.item
+ else
+-- check is_integer_32: False end
+ end
+ end
+
+ sql_read_string (a_index: INTEGER): detachable STRING
+ -- Retrieved value at `a_index' position in `item'.
+ local
+ l_item: like sql_item
+ do
+ l_item := sql_item (a_index)
+ if attached {READABLE_STRING_32} l_item as l_string then
+ Result := l_string
+ elseif attached {BOOLEAN} l_item as l_boolean then
+ Result := l_boolean.out
+ elseif attached {BOOLEAN_REF} l_item as l_boolean_ref then
+ Result := l_boolean_ref.item.out
+ else
+-- check is_string: False end
+ end
+ end
+
+ sql_read_string_32 (a_index: INTEGER): detachable STRING_32
+ -- Retrieved value at `a_index' position in `item'.
+ local
+ l_item: like sql_item
+ do
+ -- FIXME: handle string_32 !
+ l_item := sql_item (a_index)
+ if attached {READABLE_STRING_32} l_item as l_string then
+ Result := l_string
+ else
+ if attached sql_read_string (a_index) as s8 then
+ Result := s8.to_string_32 -- FIXME
+ end
+ end
+ end
+
+ sql_read_date_time (a_index: INTEGER): detachable DATE_TIME
+ -- Retrieved value at `a_index' position in `item'.
+ local
+ l_item: like sql_item
+ do
+ l_item := sql_item (a_index)
+ if attached {DATE_TIME} l_item as dt then
+ Result := dt
+ else
+-- check is_date_time: False end
+ end
+ end
+
+ sql_read_boolean (a_index: INTEGER): detachable BOOLEAN
+ -- Retrieved value at `a_index' position in `item'.
+ local
+ l_item: like sql_item
+ do
+ l_item := sql_item (a_index)
+ if attached {BOOLEAN} l_item as l_boolean then
+ Result := l_boolean
+ elseif attached {BOOLEAN_REF} l_item as l_boolean_ref then
+ Result := l_boolean_ref.item
+ else
+ check is_boolean: False end
+ end
+ end
+
+end
diff --git a/library/src/persistence/node/cms_node_storage.e b/library/src/persistence/node/cms_node_storage.e
new file mode 100644
index 0000000..6d036c7
--- /dev/null
+++ b/library/src/persistence/node/cms_node_storage.e
@@ -0,0 +1,97 @@
+note
+ description: "Summary description for {CMS_NODE_STORAGE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_NODE_STORAGE
+
+inherit
+ SHARED_LOGGER
+
+feature -- Error Handling
+
+ error_handler: ERROR_HANDLER
+ -- Error handler.
+ deferred
+ end
+
+feature -- Access
+
+ nodes: LIST [CMS_NODE]
+ -- List of nodes.
+ deferred
+ end
+
+ recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
+ -- List of recent `a_count' nodes with an offset of `lower'.
+ deferred
+ end
+
+ node (a_id: INTEGER_64): detachable CMS_NODE
+ -- Retrieve node by id `a_id', if any.
+ require
+ a_id > 0
+ deferred
+ end
+
+ node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
+ -- Node's author. if any.
+ require
+ valid_node: a_id >0
+ deferred
+ end
+
+feature -- Change: Node
+
+ save_node (a_node: CMS_NODE)
+ -- Save node `a_node'.
+ require
+ valid_user: attached a_node.author as l_author implies l_author.id > 0
+ deferred
+ end
+
+ delete_node (a_id: INTEGER_64)
+ -- Remove node by id `a_id'.
+ require
+ valid_node_id: a_id > 0
+ deferred
+ end
+
+ update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE)
+ -- Update node content `a_node'.
+ -- The user `a_id' is an existing or new collaborator.
+ require
+ valid_node_id: a_node.id > 0
+ valid_user_id: a_id > 0
+ deferred
+ end
+
+ update_node_title (a_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_id' is an existing or new collaborator.
+ require
+ valid_node_id: a_node_id > 0
+ valid_user_id: a_id > 0
+ deferred
+ end
+
+ update_node_summary (a_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_id' is an existing or new collaborator.
+ require
+ valid_id: a_node_id > 0
+ deferred
+ end
+
+ update_node_content (a_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_id' is an existing or new collaborator.
+ require
+ valid_id: a_node_id > 0
+ valid_user_id: a_id > 0
+ deferred
+ end
+
+end
diff --git a/library/src/persistence/node/cms_node_storage_sql.e b/library/src/persistence/node/cms_node_storage_sql.e
new file mode 100644
index 0000000..a836a03
--- /dev/null
+++ b/library/src/persistence/node/cms_node_storage_sql.e
@@ -0,0 +1,341 @@
+note
+ description: "Summary description for {CMS_NODE_STORAGE_SQL}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_NODE_STORAGE_SQL
+
+inherit
+ CMS_NODE_STORAGE
+
+ CMS_STORAGE_SQL
+
+ REFACTORING_HELPER
+
+ SHARED_LOGGER
+
+feature -- Access
+
+ nodes: LIST [CMS_NODE]
+ -- List of nodes.
+ do
+ create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
+
+ error_handler.reset
+ log.write_information (generator + ".nodes")
+
+ from
+ sql_query (select_nodes, Void)
+ sql_post_execution
+ until
+ sql_after
+ loop
+ if attached fetch_node as l_node then
+ Result.force (l_node)
+ end
+ sql_forth
+ end
+ sql_post_execution
+ end
+
+ recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
+ -- List of recent `a_count' nodes with an offset of `lower'.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
+
+ error_handler.reset
+ log.write_information (generator + ".nodes")
+
+ from
+ 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_post_execution
+ until
+ sql_after
+ loop
+ if attached fetch_node as l_node then
+ Result.force (l_node)
+ end
+ sql_forth
+ end
+ sql_post_execution
+ end
+
+ node (a_id: INTEGER_64): detachable CMS_NODE
+ -- Retrieve node by id `a_id', if any.
+ local
+ l_parameters: STRING_TABLE [ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".node")
+ create l_parameters.make (1)
+ l_parameters.put (a_id,"id")
+ sql_query (select_node_by_id, l_parameters)
+ if sql_rows_count = 1 then
+ Result := fetch_node
+ end
+ sql_post_execution
+ end
+
+ node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
+ -- Node's author for the given node id.
+ local
+ l_parameters: STRING_TABLE [ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".node_author")
+ create l_parameters.make (1)
+ l_parameters.put (a_id, "node_id")
+ sql_query (select_node_author, l_parameters)
+ if sql_rows_count >= 1 then
+ Result := fetch_author
+ end
+ sql_post_execution
+ end
+
+ nodes_count: INTEGER
+ -- Number of items nodes.
+ do
+ error_handler.reset
+ log.write_information (generator + ".nodes_count")
+ sql_query (select_nodes_count, Void)
+ if sql_rows_count = 1 then
+ Result := sql_read_integer_32 (1)
+ end
+ sql_post_execution
+ end
+
+ last_inserted_node_id: INTEGER
+ -- Last insert node id.
+ do
+ error_handler.reset
+ log.write_information (generator + ".last_inserted_node_id")
+ sql_query (Sql_last_insert_node_id, Void)
+ if sql_rows_count = 1 then
+ Result := sql_read_integer_32 (1)
+ end
+ sql_post_execution
+ end
+
+feature -- Change: Node
+
+ save_node (a_node: CMS_NODE)
+ -- Save node `a_node'.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ if a_node.has_id and attached a_node.author as l_author and then l_author.has_id then
+ update_node (l_author.id, a_node)
+ else
+ error_handler.reset
+ log.write_information (generator + ".save_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, "publication_date")
+ l_parameters.put (a_node.creation_date, "creation_date")
+ l_parameters.put (a_node.modification_date, "modification_date")
+ if
+ attached a_node.author as l_author and then
+ l_author.id > 0
+ then
+ l_parameters.put (l_author.id, "author_id")
+ end
+ sql_change (sql_insert_node, l_parameters)
+ a_node.set_id (last_inserted_node_id)
+ sql_post_execution
+ end
+ end
+
+ delete_node (a_id: INTEGER_64)
+ -- Remove node by id `a_id'.
+ local
+ l_parameters: STRING_TABLE [ANY]
+ do
+ log.write_information (generator + ".delete_node")
+
+ error_handler.reset
+ create l_parameters.make (1)
+ l_parameters.put (a_id, "id")
+ sql_change (sql_delete_node, l_parameters)
+ sql_post_execution
+
+ -- Delete from user nodes. FIXME: what is that ???
+ sql_change (sql_delete_from_user_node, l_parameters)
+ sql_post_execution
+ end
+
+ update_node (a_user_id: like {CMS_USER}.id; a_node: CMS_NODE)
+ -- Update node content `a_node'.
+ -- The user `a_user_id' is an existing or new collaborator.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".update_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, "publication_date")
+ l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
+ l_parameters.put (a_node.id, "id")
+ l_parameters.put (a_user_id, "editor")
+ sql_change (sql_update_node, l_parameters)
+ sql_post_execution
+ end
+
+ update_node_title (a_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_id' is an existing or new collaborator.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".update_node_title")
+ create l_parameters.make (3)
+ l_parameters.put (a_title, "title")
+ l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
+ l_parameters.put (a_id, "id")
+ sql_change (sql_update_node_title, l_parameters)
+ sql_post_execution
+ end
+
+ update_node_summary (a_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_id' is an existing or new collaborator.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".update_node_summary")
+ create l_parameters.make (3)
+ l_parameters.put (a_summary, "summary")
+ l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
+ l_parameters.put (a_id, "id")
+ sql_change (sql_update_node_summary, l_parameters)
+ sql_post_execution
+ end
+
+ update_node_content (a_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_id' is an existing or new collaborator.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".update_node_content")
+ create l_parameters.make (3)
+ l_parameters.put (a_content, "content")
+ l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
+ l_parameters.put (a_id, "id")
+ sql_change (sql_update_node_content, l_parameters)
+ sql_post_execution
+ end
+
+feature {NONE} -- Queries
+
+ Select_nodes_count: STRING = "select count(*) from Nodes;"
+
+ Select_nodes: STRING = "select * from Nodes;"
+ -- SQL Query to retrieve all nodes.
+
+ Select_node_by_id: STRING = "select * from Nodes where id =:id order by id desc, publication_date desc;"
+
+ Select_recent_nodes: STRING = "select * from Nodes order by id desc, publication_date desc LIMIT :rows OFFSET :offset ;"
+
+ SQL_Insert_node: STRING = "insert into nodes (title, summary, content, publication_date, creation_date, modification_date, author_id) values (:title, :summary, :content, :publication_date, :creation_date, :modification_date, :author_id);"
+ -- SQL Insert to add a new node.
+
+ SQL_Update_node_title: STRING ="update nodes SET title=:title, modification_date=:modification_date, version = version + 1 where id=:id;"
+ -- SQL update node title.
+
+ SQL_Update_node_summary: STRING ="update nodes SET summary=:summary, modification_date=:modification_date, version = version + 1 where id=:id;"
+ -- SQL update node summary.
+
+ SQL_Update_node_content: STRING ="update nodes SET content=:content, modification_date=:modification_date, version = version + 1 where id=:id;"
+ -- SQL node content.
+
+ Slq_update_editor: STRING ="update nodes SET editor_id=:users_id where id=:nodes_id;"
+ -- SQL node content.
+
+ SQL_Update_node : STRING = "update nodes SET title=:title, summary=:summary, content=:content, publication_date=:publication_date, modification_date=:modification_date, version = version + 1, editor_id=:editor where id=:id;"
+ -- SQL node.
+
+ SQL_Delete_node: STRING = "delete from nodes where id=:id;"
+
+ Sql_update_node_author: STRING = "update nodes SET author_id=:user_id where id=:id;"
+
+ Sql_last_insert_node_id: STRING = "SELECT MAX(id) from nodes;"
+
+feature {NONE} -- Sql Queries: USER_ROLES collaborators, author
+
+ Sql_insert_users_nodes: STRING = "insert into users_nodes (users_id, nodes_id) values (:users_id, :nodes_id);"
+
+ select_node_collaborators: STRING = "SELECT * FROM Users INNER JOIN users_nodes ON users.id=users_nodes.users_id and users_nodes.nodes_id = :node_id;"
+
+ Select_user_author: STRING = "SELECT * FROM Nodes INNER JOIN users ON nodes.author_id=users.id and users.id = :user_id;"
+
+ Select_node_author: STRING = "SELECT * FROM Users INNER JOIN nodes ON nodes.author_id=users.id and nodes.id =:node_id;"
+
+ Select_user_collaborator: STRING = "SELECT * FROM Nodes INNER JOIN users_nodes ON users_nodes.nodes_id = nodes.id and users_nodes.users_id = :user_id;"
+
+ Select_exist_user_node: STRING= "Select Count(*) from Users_nodes where users_id=:user_id and nodes_id=:node_id;"
+
+ sql_delete_from_user_node: STRING = "delete from users_nodes where nodes_id=:id"
+
+feature {NONE} -- Implementation
+
+ fetch_node: CMS_NODE
+ do
+ create Result.make ("", "", "")
+ if attached sql_read_integer_32 (1) as l_id then
+ Result.set_id (l_id)
+ end
+ if attached sql_read_date_time (2) as l_publication_date then
+ Result.set_publication_date (l_publication_date)
+ end
+ if attached sql_read_date_time (3) as l_creation_date then
+ Result.set_creation_date (l_creation_date)
+ end
+ if attached sql_read_date_time (4) as l_modif_date then
+ Result.set_modification_date (l_modif_date)
+ end
+ if attached sql_read_string_32 (5) as l_title then
+ Result.set_title (l_title)
+ end
+ if attached sql_read_string_32 (6) as l_summary then
+ Result.set_summary (l_summary)
+ end
+ if attached sql_read_string (7) as l_content then
+ Result.set_content (l_content)
+ end
+ end
+
+ fetch_author: detachable CMS_USER
+ do
+ if attached sql_read_string_32 (2) as l_name and then not l_name.is_whitespace then
+ create Result.make (l_name)
+ if attached sql_read_integer_32 (1) as l_id then
+ Result.set_id (l_id)
+ end
+ if attached sql_read_string (3) as l_password then
+ -- FIXME: should we return the password here ???
+ Result.set_hashed_password (l_password)
+ end
+ if attached sql_read_string (5) as l_email then
+ Result.set_email (l_email)
+ end
+ else
+ check expected_valid_user: False end
+ end
+ end
+
+end
diff --git a/library/src/persistence/user/cms_user_storage.e b/library/src/persistence/user/cms_user_storage.e
new file mode 100644
index 0000000..6bfc9a7
--- /dev/null
+++ b/library/src/persistence/user/cms_user_storage.e
@@ -0,0 +1,120 @@
+note
+ description: "Summary description for {CMS_USER_STORAGE}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_USER_STORAGE
+
+inherit
+ SHARED_LOGGER
+
+feature -- Error Handling
+
+ error_handler: ERROR_HANDLER
+ -- Error handler.
+ deferred
+ end
+
+feature -- Access
+
+ has_user: BOOLEAN
+ -- Has any user?
+ deferred
+ end
+
+ users: LIST [CMS_USER]
+ -- List of users.
+ deferred
+ end
+
+ user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
+ -- User with id `a_id', if any.
+ require
+ a_id > 0
+ deferred
+ ensure
+ same_id: Result /= Void implies Result.id = a_id
+ password: Result /= Void implies Result.password /= Void
+ end
+
+ user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
+ -- User with name `a_name', if any.
+ require
+ a_name /= Void and then not a_name.is_empty
+ deferred
+ ensure
+ same_name: Result /= Void implies a_name ~ Result.name
+ password: Result /= Void implies Result.password /= Void
+ end
+
+ user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
+ -- User with name `a_email', if any.
+ deferred
+ ensure
+ same_email: Result /= Void implies a_email ~ Result.email
+ password: Result /= Void implies Result.password /= Void
+ end
+
+ is_valid_credential (a_u, a_p: READABLE_STRING_32): BOOLEAN
+ -- Does account with username `a_username' and password `a_password' exist?
+ deferred
+ end
+
+feature -- Change: user
+
+ save_user (a_user: CMS_USER)
+ -- Save user `a_user'.
+ deferred
+ end
+
+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_role_has_permission (a_role: CMS_USER_ROLE; s: READABLE_STRING_8): BOOLEAN
+ do
+ Result := a_role.has_permission (s)
+ end
+
+ user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
+ -- User role by id `a_id', if any.
+ deferred
+ end
+
+ user_roles: LIST [CMS_USER_ROLE]
+ -- Possible list of user roles.
+ deferred
+ end
+
+feature -- Change: roles and permissions
+
+ save_user_role (a_user_role: CMS_USER_ROLE)
+ -- Save user role `a_user_role'
+ deferred
+ end
+
+end
diff --git a/library/src/persistence/user/cms_user_storage_sql.e b/library/src/persistence/user/cms_user_storage_sql.e
new file mode 100644
index 0000000..b0ab971
--- /dev/null
+++ b/library/src/persistence/user/cms_user_storage_sql.e
@@ -0,0 +1,285 @@
+note
+ description: "Summary description for {CMS_USER_STORAGE_SQL}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_USER_STORAGE_SQL
+
+inherit
+ CMS_USER_STORAGE
+
+ CMS_STORAGE_SQL
+
+ REFACTORING_HELPER
+
+ SHARED_LOGGER
+
+feature -- Access: user
+
+ has_user: BOOLEAN
+ -- Has any user?
+ do
+ Result := user_count > 0
+ end
+
+ user_count: INTEGER
+ -- Number of items users.
+ do
+ error_handler.reset
+ log.write_information (generator + ".user_count")
+
+ sql_query (select_users_count, Void)
+ if sql_rows_count = 1 then
+ Result := sql_read_integer_32 (1)
+ end
+ sql_post_execution
+ end
+
+ users: LIST [CMS_USER]
+ do
+ create {ARRAYED_LIST [CMS_USER]} Result.make (0)
+
+ error_handler.reset
+ log.write_information (generator + ".all_users")
+
+ from
+ sql_query (select_users, Void)
+ sql_post_execution
+ until
+ sql_after
+ loop
+ if attached fetch_user as l_user then
+ Result.force (l_user)
+ end
+ sql_forth
+ end
+ sql_post_execution
+ end
+
+ user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
+ -- User for the given id `a_id', if any.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".user")
+ create l_parameters.make (1)
+ l_parameters.put (a_id, "id")
+ sql_query (select_user_by_id, l_parameters)
+ if sql_rows_count = 1 then
+ Result := fetch_user
+ else
+ check no_more_than_one: sql_rows_count = 0 end
+ end
+ sql_post_execution
+ end
+
+ user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
+ -- User for the given name `a_name', if any.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".user_by_name")
+ create l_parameters.make (1)
+ l_parameters.put (a_name, "name")
+ sql_query (select_user_by_name, l_parameters)
+ if sql_rows_count = 1 then
+ Result := fetch_user
+ else
+ check no_more_than_one: sql_rows_count = 0 end
+ end
+ sql_post_execution
+ end
+
+ user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
+ -- User for the given email `a_email', if any.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".user_by_email")
+ create l_parameters.make (1)
+ l_parameters.put (a_email, "email")
+ sql_query (select_user_by_email, l_parameters)
+ if sql_rows_count = 1 then
+ Result := fetch_user
+ else
+ check no_more_than_one: sql_rows_count = 0 end
+ end
+ sql_post_execution
+ end
+
+ is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
+ local
+ l_security: SECURITY_PROVIDER
+ do
+ if attached user_salt (l_auth_login) as l_hash then
+ if attached user_by_name (l_auth_login) as l_user then
+ create l_security
+ if
+ attached l_user.hashed_password as l_hashed_password and then
+ l_security.password_hash (l_auth_password, l_hash).is_case_insensitive_equal (l_hashed_password)
+ then
+ Result := True
+ else
+ log.write_information (generator + ".is_valid_credential User: wrong username or password" )
+ end
+ else
+ log.write_information (generator + ".is_valid_credential User:" + l_auth_login + "does not exist" )
+ end
+ end
+
+ end
+
+feature -- Change: user
+
+ save_user (a_user: CMS_USER)
+ -- Add a new user `a_user'.
+ do
+ if
+ attached a_user.password as l_password and then
+ attached a_user.email as l_email
+ then
+ sql_begin_transaction
+ new_user (a_user)
+ sql_commit_transaction
+ else
+ debug ("refactor_fixme")
+ fixme ("maybe we should not always carry password, in this case, to implement the else part..")
+ end
+ end
+ end
+
+feature -- Access: roles and permissions
+
+ user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
+ do
+ to_implement (generator + ".user_role_by_id")
+ end
+
+ user_roles: LIST [CMS_USER_ROLE]
+ do
+ to_implement (generator + ".user_roles")
+ create {ARRAYED_LIST[CMS_USER_ROLE]} Result.make (0)
+ end
+
+feature -- Change: roles and permissions
+
+ save_user_role (a_user_role: CMS_USER_ROLE)
+ do
+ to_implement (generator + ".save_user_role")
+ end
+
+feature {NONE} -- Implementation
+
+ user_salt (a_username: READABLE_STRING_32): detachable READABLE_STRING_8
+ -- User salt for the given user `a_username', if any.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".user_salt")
+ create l_parameters.make (1)
+ l_parameters.put (a_username, "name")
+ sql_query (select_salt_by_username, l_parameters)
+ if sql_rows_count = 1 then
+ if attached sql_read_string (1) as l_salt then
+ Result := l_salt
+ end
+ end
+ sql_post_execution
+ end
+
+ new_user (a_user: CMS_USER)
+ -- Add a new user `a_user'.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ l_password_salt, l_password_hash: STRING
+ l_security: SECURITY_PROVIDER
+ do
+ if
+ attached a_user.password as l_password and then
+ attached a_user.email as l_email
+ then
+ error_handler.reset
+ create l_security
+ l_password_salt := l_security.salt
+ l_password_hash := l_security.password_hash (l_password, l_password_salt)
+
+ log.write_information (generator + ".new_user")
+ create l_parameters.make (4)
+ l_parameters.put (a_user.name, "username")
+ l_parameters.put (l_password_hash, "password")
+ l_parameters.put (l_password_salt, "salt")
+ l_parameters.put (l_email, "email")
+
+ sql_change (sql_insert_user, l_parameters)
+ else
+ -- set error
+ error_handler.add_custom_error (-1, "bad request" , "Missing password or email")
+ end
+ sql_post_execution
+ end
+
+ fetch_user: detachable CMS_USER
+ local
+ l_id: INTEGER_64
+ l_name: detachable READABLE_STRING_32
+ do
+ if attached sql_read_integer_32 (1) as i then
+ l_id := i
+ 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
+
+ if Result /= Void then
+ if attached sql_read_string (3) as l_password then
+ -- FIXME: should we return the password here ???
+ Result.set_hashed_password (l_password)
+ end
+ if attached sql_read_string (5) as l_email then
+ Result.set_email (l_email)
+ end
+ else
+ check expected_valid_user: False end
+ end
+ end
+
+feature {NONE} -- Sql Queries: USER
+
+ Select_users_count: STRING = "select count(*) from Users;"
+ -- Number of users.
+
+ Select_users: STRING = "select * from Users;"
+ -- List of users.
+
+ Select_user_by_id: STRING = "select * from Users where id =:id;"
+ -- Retrieve user by id if exists.
+
+ Select_user_by_name: STRING = "select * from Users where username =:name;"
+ -- Retrieve user by name if exists.
+
+ 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 username =:name;"
+ -- Retrieve salt by username if exists.
+
+ SQL_Insert_user: STRING = "insert into users (username, password, salt, email) values (:username, :password, :salt, :email);"
+ -- SQL Insert to add a new node.
+
+
+end
diff --git a/library/persistence/implementation/common/security/security_provider.e b/library/src/security/security_provider.e
similarity index 92%
rename from library/persistence/implementation/common/security/security_provider.e
rename to library/src/security/security_provider.e
index ae40a8c..ff2c9b2 100644
--- a/library/persistence/implementation/common/security/security_provider.e
+++ b/library/src/security/security_provider.e
@@ -34,10 +34,16 @@ feature -- Access
Result.keep_head (Result.count - 2)
end
- password_hash (a_password, a_salt: STRING): STRING
+ password_hash (a_password: READABLE_STRING_GENERAL; a_salt: STRING): STRING
-- Password hash based on password `a_password' and salt value `a_salt'.
+ local
+ utf: UTF_CONVERTER
+ s: STRING
do
- Result := sha1_string (a_password + a_salt )
+ create s.make (a_password.count + a_salt.count)
+ utf.utf_32_string_into_utf_8_string_8 (a_password, s)
+ s.append (a_salt)
+ Result := sha1_string (s)
end
feature {NONE} -- Implementation
diff --git a/library/src/service/cms_api.e b/library/src/service/cms_api.e
index c6abbe0..119c165 100644
--- a/library/src/service/cms_api.e
+++ b/library/src/service/cms_api.e
@@ -7,9 +7,20 @@ class
CMS_API
inherit
+ ANY
REFACTORING_HELPER
+ SHARED_HTML_ENCODER
+ export
+ {NONE} all
+ end
+
+ SHARED_WSF_PERCENT_ENCODER
+ export
+ {NONE} all
+ end
+
create
make
@@ -83,10 +94,10 @@ feature -- Access: Node
debug ("refactor_fixme")
fixme ("Implementation")
end
- Result := storage.recent_nodes (0, 10)
+ Result := storage.nodes
end
- recent_nodes (a_offset, a_rows: INTEGER): LIST[CMS_NODE]
+ recent_nodes (a_offset, a_rows: INTEGER): LIST [CMS_NODE]
-- List of the `a_rows' most recent nodes starting from `a_offset'.
do
Result := storage.recent_nodes (a_offset, a_rows)
@@ -174,6 +185,20 @@ feature -- Change User
end
end
+feature -- Helpers
+
+ html_encoded (a_string: READABLE_STRING_GENERAL): STRING_8
+ -- `a_string' encoded for html output.
+ do
+ Result := html_encoder.general_encoded_string (a_string)
+ end
+
+ percent_encoded (a_string: READABLE_STRING_GENERAL): STRING_8
+ -- `a_string' encoded with percent encoding, mainly used for url.
+ do
+ Result := percent_encoder.percent_encoded_string (a_string)
+ end
+
feature -- Layout
module_configuration (a_module_name: READABLE_STRING_GENERAL; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER
diff --git a/library/src/service/response/not_implemented_error_cms_response.e b/library/src/service/response/not_implemented_error_cms_response.e
index b2c9e81..d4ab328 100644
--- a/library/src/service/response/not_implemented_error_cms_response.e
+++ b/library/src/service/response/not_implemented_error_cms_response.e
@@ -32,7 +32,9 @@ feature -- Execution
do
set_title ("Not Implemented")
set_page_title (Void)
- set_main_content (request.percent_encoded_path_info + " is not implemented!")
+ if main_content = Void then
+ set_main_content (request.percent_encoded_path_info + " is not implemented!")
+ end
end
end