+
diff --git a/library/persistence/implementation/common/cms_storage_store_sql.e b/library/persistence/implementation/common/cms_storage_store_sql.e
new file mode 100644
index 0000000..0b8c32c
--- /dev/null
+++ b/library/persistence/implementation/common/cms_storage_store_sql.e
@@ -0,0 +1,106 @@
+note
+ description: "Summary description for {CMS_STORAGE_STORE_SQL}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_STORAGE_STORE_SQL
+
+inherit
+ CMS_STORAGE
+
+ CMS_STORAGE_SQL
+
+feature {NONE} -- Initialization
+
+ make (a_connection: DATABASE_CONNECTION)
+ --
+ require
+ is_connected: a_connection.is_connected
+ do
+ connection := a_connection
+ log.write_information (generator + ".make - is database connected? "+ a_connection.is_connected.out )
+
+ create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
+
+ create error_handler.make
+-- error_handler.add_synchronization (db_handler.database_error_handler)
+ end
+
+feature {NONE} -- Implementation
+
+ db_handler: DATABASE_HANDLER
+
+ connection: DATABASE_CONNECTION
+ -- Current database connection.
+
+feature -- Query
+
+ sql_post_execution
+ -- Post database execution.
+ do
+ error_handler.append (db_handler.database_error_handler)
+ if error_handler.has_error then
+ log.write_critical (generator + ".post_execution " + error_handler.as_string_representation)
+ end
+ end
+
+ sql_begin_transaction
+ do
+ 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
+ check_sql_query_validity (a_sql_statement, a_params)
+ db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
+ db_handler.execute_query
+ end
+
+ sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+ do
+ check_sql_query_validity (a_sql_statement, a_params)
+ db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
+ db_handler.execute_change
+ end
+
+ sql_rows_count: INTEGER
+ -- Number of rows for last sql execution.
+ do
+ Result := db_handler.count
+ end
+
+ sql_start
+ -- Set the cursor on first element.
+ do
+ db_handler.start
+ 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
+ check has_item_at_index: False end
+ end
+ end
+
+end
diff --git a/library/persistence/implementation/mysql/src/cms_storage_mysql.e b/library/persistence/implementation/mysql/src/cms_storage_mysql.e
index feaafae..2bfd7ed 100644
--- a/library/persistence/implementation/mysql/src/cms_storage_mysql.e
+++ b/library/persistence/implementation/mysql/src/cms_storage_mysql.e
@@ -7,8 +7,9 @@ class
CMS_STORAGE_MYSQL
inherit
-
CMS_STORAGE
+
+ CMS_STORAGE_STORE_SQL
CMS_USER_STORAGE_MYSQL
@@ -19,85 +20,93 @@ inherit
create
make
-feature {NONE} -- Initialization
+--feature {NONE} -- Initialization
- make (a_connection: DATABASE_CONNECTION)
- --
- require
- is_connected: a_connection.is_connected
- do
- connection := a_connection
- log.write_information (generator + ".make - is database connected? "+ a_connection.is_connected.out )
+-- make (a_connection: DATABASE_CONNECTION)
+-- --
+-- require
+-- is_connected: a_connection.is_connected
+-- do
+-- connection := a_connection
+-- log.write_information (generator + ".make - is database connected? "+ a_connection.is_connected.out )
- create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
+-- create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
- create error_handler.make
--- error_handler.add_synchronization (db_handler.database_error_handler)
- end
+-- create error_handler.make
+---- error_handler.add_synchronization (db_handler.database_error_handler)
+-- end
- db_handler: DATABASE_HANDLER
+-- db_handler: DATABASE_HANDLER
- connection: DATABASE_CONNECTION
- -- Current database connection.
+-- connection: DATABASE_CONNECTION
+-- -- Current database connection.
-feature -- Query
+--feature -- Query
- sql_post_execution
- -- Post database execution.
- do
- error_handler.append (db_handler.database_error_handler)
- if error_handler.has_error then
- log.write_critical (generator + ".post_execution " + error_handler.as_string_representation)
- end
- end
+-- sql_post_execution
+-- -- Post database execution.
+-- do
+-- error_handler.append (db_handler.database_error_handler)
+-- if error_handler.has_error then
+-- log.write_critical (generator + ".post_execution " + error_handler.as_string_representation)
+-- end
+-- end
- sql_begin_transaction
- do
- connection.begin_transaction
- end
+-- sql_begin_transaction
+-- do
+-- connection.begin_transaction
+-- end
- sql_commit_transaction
- do
- connection.commit
- 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, a_params))
- db_handler.execute_query
- end
+-- sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+-- do
+-- check_sql_query_validity (a_sql_statement, a_params)
+-- db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
+-- 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, a_params))
- db_handler.execute_change
- end
+-- sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+-- do
+-- check_sql_query_validity (a_sql_statement, a_params)
+-- db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
+-- db_handler.execute_change
+-- end
- sql_rows_count: INTEGER
- -- Number of rows for last sql execution.
- do
- Result := db_handler.count
- 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_start
+-- -- Set the cursor on first element.
+-- do
+-- db_handler.start
+-- end
- sql_forth
- -- Fetch next row from last sql execution, if any.
- do
- db_handler.forth
- end
+-- sql_after: BOOLEAN
+-- -- Are there no more items to iterate over?
+-- do
+-- Result := db_handler.after
+-- 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
- check has_item_at_index: False end
- end
- 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
+-- check has_item_at_index: False end
+-- end
+-- end
end
diff --git a/library/persistence/implementation/sqlite/scripts/create_database.sql b/library/persistence/implementation/sqlite/scripts/create_database.sql
deleted file mode 100644
index 4b9a157..0000000
--- a/library/persistence/implementation/sqlite/scripts/create_database.sql
+++ /dev/null
@@ -1,61 +0,0 @@
--- Creator: MySQL Workbench 6.1.7/ExportSQLite plugin 2009.12.02
--- Author: javier
--- Caption: New Model
--- Project: Name of the project
--- Changed: 2014-09-16 23:12
--- Created: 2014-09-16 23:12
-PRAGMA foreign_keys = OFF;
-
--- Schema: cms_dev
-BEGIN;
-CREATE TABLE "nodes"(
- "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("id">=0),
- "publication_date" DATE NOT NULL,
- "creation_date" DATE NOT NULL,
- "modification_date" DATE NOT NULL,
- "title" VARCHAR(255) NOT NULL,
- "summary" TEXT NOT NULL,
- "content" MEDIUMTEXT NOT NULL
-);
-CREATE TABLE "roles"(
- "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("id">=0),
- "role" VARCHAR(100) NOT NULL,
- CONSTRAINT "role"
- UNIQUE("role")
-);
-CREATE TABLE "users"(
- "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("id">=0),
- "username" VARCHAR(100) NOT NULL,
- "password" VARCHAR(100) NOT NULL,
- "salt" VARCHAR(100) NOT NULL,
- "email" VARCHAR(250) NOT NULL,
- CONSTRAINT "username"
- UNIQUE("username")
-);
-CREATE TABLE "users_nodes"(
- "users_id" INTEGER NOT NULL CHECK("users_id">=0),
- "nodes_id" INTEGER NOT NULL CHECK("nodes_id">=0),
- PRIMARY KEY("users_id","nodes_id"),
- CONSTRAINT "fk_users_has_nodes_nodes1"
- FOREIGN KEY("nodes_id")
- REFERENCES "nodes"("id"),
- CONSTRAINT "fk_users_has_nodes_users"
- FOREIGN KEY("users_id")
- REFERENCES "users"("id")
-);
-CREATE INDEX "users_nodes.fk_users_has_nodes_nodes1_idx" ON "users_nodes"("nodes_id");
-CREATE INDEX "users_nodes.fk_users_has_nodes_users_idx" ON "users_nodes"("users_id");
-CREATE TABLE "users_roles"(
- "users_id" INTEGER NOT NULL CHECK("users_id">=0),
- "roles_id" INTEGER NOT NULL CHECK("roles_id">=0),
- PRIMARY KEY("users_id","roles_id"),
- CONSTRAINT "fk_users_has_roles_roles1"
- FOREIGN KEY("roles_id")
- REFERENCES "roles"("id"),
- CONSTRAINT "fk_users_has_roles_users1"
- FOREIGN KEY("users_id")
- REFERENCES "users"("id")
-);
-CREATE INDEX "users_roles.fk_users_has_roles_roles1_idx" ON "users_roles"("roles_id");
-CREATE INDEX "users_roles.fk_users_has_roles_users1_idx" ON "users_roles"("users_id");
-COMMIT;
diff --git a/library/persistence/implementation/sqlite/scripts/schema.sql b/library/persistence/implementation/sqlite/scripts/schema.sql
new file mode 100644
index 0000000..0dffacb
--- /dev/null
+++ b/library/persistence/implementation/sqlite/scripts/schema.sql
@@ -0,0 +1,36 @@
+PRAGMA foreign_keys = OFF;
+
+BEGIN;
+CREATE TABLE "users"(
+ "uid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("uid">=0),
+ "name" VARCHAR(100) NOT NULL,
+ "password" VARCHAR(100) NOT NULL,
+ "salt" VARCHAR(100) NOT NULL,
+ "email" VARCHAR(250) NOT NULL,
+ "status" INTEGER,
+ "created" DATETIME NOT NULL,
+ "signed" DATETIME,
+ CONSTRAINT "name"
+ UNIQUE("name")
+);
+
+CREATE TABLE "users_roles"(
+ "rid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("rid">=0),
+ "role" VARCHAR(100) NOT NULL,
+ CONSTRAINT "role"
+ UNIQUE("role")
+);
+
+CREATE TABLE "nodes"(
+ "nid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nid">=0),
+ "version" INTEGER,
+ "type" INTEGER,
+ "title" VARCHAR(255) NOT NULL,
+ "summary" TEXT NOT NULL,
+ "content" MEDIUMTEXT NOT NULL,
+ "author" INTEGER,
+ "publish" DATETIME,
+ "created" DATETIME NOT NULL,
+ "changed" DATETIME NOT NULL
+);
+COMMIT;
diff --git a/library/persistence/implementation/sqlite/scripts/tables.sql b/library/persistence/implementation/sqlite/scripts/tables.sql
deleted file mode 100644
index 4b1a4ba..0000000
--- a/library/persistence/implementation/sqlite/scripts/tables.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-DROP TABLE IF EXISTS nodes;
-
-CREATE TABLE nodes
-(
- id smallint unsigned NOT NULL auto_increment,
- publication_date date NOT NULL, #When the article was published
- creation_date date NOT NULL, #When the article was created
- modification_date date NOT NULL, #When the article was updated
- title varchar(255) NOT NULL, #Full title of the article
- summary text NOT NULL, #A short summary of the articule
- content mediumtext NOT NULL, #The HTML content of the article
-
- PRIMARY KEY (ID)
-);
\ No newline at end of file
diff --git a/library/persistence/implementation/sqlite/src/cms_node_storage_sqlite.e b/library/persistence/implementation/sqlite/src/cms_node_storage_sqlite.e
index 6cafa70..94641a7 100644
--- a/library/persistence/implementation/sqlite/src/cms_node_storage_sqlite.e
+++ b/library/persistence/implementation/sqlite/src/cms_node_storage_sqlite.e
@@ -9,6 +9,67 @@ deferred class
inherit
CMS_NODE_STORAGE_SQL
+ redefine
+ nodes, recent_nodes
+ end
+feature {NONE} -- Implementation
+
+ db_handler: DATABASE_HANDLER
+ deferred
+ end
+
+feature -- Access
+
+ nodes: LIST [CMS_NODE]
+ -- List of nodes.
+ do
+ create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
+ across nodes_iterator as ic loop
+ Result.force (ic.item)
+ end
+ end
+
+ recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
+ -- List of recent `a_count' nodes with an offset of `lower'.
+ do
+ create {ARRAYED_LIST [CMS_NODE]} Result.make (a_count)
+ across recent_nodes_iterator (a_lower, a_count) as c loop
+ Result.force (c.item)
+ end
+ end
+
+feature -- Access: iterator
+
+ nodes_iterator: DATABASE_ITERATION_CURSOR [CMS_NODE]
+ -- List of nodes.
+ local
+ l_parameters: STRING_TABLE [ANY]
+ do
+ error_handler.reset
+ log.write_information (generator + ".nodes_iterator")
+ create l_parameters.make (0)
+ sql_query (select_nodes, l_parameters)
+ sql_post_execution
+ create Result.make (db_handler, agent fetch_node)
+ end
+
+ recent_nodes_iterator (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
+ -- FIXME: check implementation...
+ error_handler.reset
+ log.write_information (generator + ".recent_nodes_iterator")
+ create l_parameters.make (2)
+ l_parameters.put (a_rows, "rows")
+ l_parameters.put (a_lower, "offset")
+ create l_query.make_from_string (select_recent_nodes)
+ sql_query (l_query, l_parameters)
+ create Result.make (db_handler, agent fetch_node)
+ sql_post_execution
+ end
end
diff --git a/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e b/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e
index 6fccade..5ab9659 100644
--- a/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e
+++ b/library/persistence/implementation/sqlite/src/cms_storage_sqlite.e
@@ -8,6 +8,8 @@ class
inherit
CMS_STORAGE
+
+ CMS_STORAGE_STORE_SQL
CMS_USER_STORAGE_SQLITE
@@ -18,85 +20,93 @@ inherit
create
make
-feature {NONE} -- Initialization
+--feature {NONE} -- Initialization
- make (a_connection: DATABASE_CONNECTION)
- --
- require
- is_connected: a_connection.is_connected
- do
- connection := a_connection
- log.write_information (generator + ".make_with_database is database connected? "+ a_connection.is_connected.out )
+-- make (a_connection: DATABASE_CONNECTION)
+-- --
+-- require
+-- is_connected: a_connection.is_connected
+-- do
+-- 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 {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
- create error_handler.make
--- error_handler.add_synchronization (db_handler.database_error_handler)
- end
+-- create error_handler.make
+---- error_handler.add_synchronization (db_handler.database_error_handler)
+-- end
- db_handler: DATABASE_HANDLER
+-- db_handler: DATABASE_HANDLER
- connection: DATABASE_CONNECTION
- -- Current database connection.
+-- connection: DATABASE_CONNECTION
+-- -- Current database connection.
-feature -- Access: user
+--feature -- Access: user
- sql_post_execution
- -- Post database execution.
- do
- error_handler.append (db_handler.database_error_handler)
- if error_handler.has_error then
- log.write_critical (generator + ".post_execution " + error_handler.as_string_representation)
- end
- end
+-- sql_post_execution
+-- -- Post database execution.
+-- do
+-- error_handler.append (db_handler.database_error_handler)
+-- if error_handler.has_error then
+-- log.write_critical (generator + ".post_execution " + error_handler.as_string_representation)
+-- end
+-- end
- sql_begin_transaction
- do
- connection.begin_transaction
- end
+-- sql_begin_transaction
+-- do
+-- connection.begin_transaction
+-- end
- sql_commit_transaction
- do
- connection.commit
- 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, a_params))
- db_handler.execute_query
- end
+-- sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+-- do
+-- check_sql_query_validity (a_sql_statement, a_params)
+-- db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
+-- 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, a_params))
- db_handler.execute_change
- end
+-- sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
+-- do
+-- check_sql_query_validity (a_sql_statement, a_params)
+-- db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
+-- db_handler.execute_change
+-- end
- sql_rows_count: INTEGER
- -- Number of rows for last sql execution.
- do
- Result := db_handler.count
- 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_start
+-- -- Set the cursor on first element.
+-- do
+-- db_handler.start
+-- end
- sql_forth
- -- Fetch next row from last sql execution, if any.
- do
- db_handler.forth
- end
+-- sql_after: BOOLEAN
+-- -- Are there no more items to iterate over?
+-- do
+-- Result := db_handler.after
+-- 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
- check has_item_at_index: False end
- end
- 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
+-- check has_item_at_index: False end
+-- end
+-- end
end
diff --git a/library/src/modules/node/node_module.e b/library/src/modules/node/node_module.e
index a1b3c4c..fff007d 100644
--- a/library/src/modules/node/node_module.e
+++ b/library/src/modules/node/node_module.e
@@ -162,21 +162,23 @@ feature -- Handler
l_user: CMS_USER
l_node: CMS_NODE
do
- create {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE} r.make (req, res, a_api)
+ create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api)
if attached a_api.user_by_name ("foo") as u then
l_user := u
else
create l_user.make ("foo")
l_user.set_password ("foobar#")
- l_user.set_email ("jfiat@eiffel.com")
+ l_user.set_email ("test@example.com")
a_api.new_user (l_user)
end
- create l_node.make ({STRING_32} "This is a content", {STRING_32} "And a summary", {STRING_32} "Nice title")
- l_node.set_author (l_user)
- a_api.new_node (l_node)
+ if a_api.nodes_count = 0 then
+ create l_node.make ({STRING_32} "This is a content", {STRING_32} "And a summary", {STRING_32} "Nice title")
+ l_node.set_author (l_user)
+ a_api.new_node (l_node)
+ end
- create s.make_from_string ("Sorry: listing the CMS nodes is not yet implemented.
")
+ create s.make_from_string ("Nodes:
")
if attached a_api.nodes as lst then
across
lst as ic
@@ -191,7 +193,7 @@ feature -- Handler
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.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
", Void), "highlighted")
r.execute
end
diff --git a/library/src/persistence/cms_storage_null.e b/library/src/persistence/cms_storage_null.e
index 00a1fcd..e54e5ac 100644
--- a/library/src/persistence/cms_storage_null.e
+++ b/library/src/persistence/cms_storage_null.e
@@ -7,13 +7,13 @@ class
CMS_STORAGE_NULL
inherit
-
CMS_STORAGE
redefine
default_create
select
default_create
end
+
REFACTORING_HELPER
rename
default_create as default_create_rh
@@ -70,11 +70,16 @@ feature -- User Nodes
feature -- Change: user
- save_user (a_user: CMS_USER)
+ new_user (a_user: CMS_USER)
-- Add a new user `a_user'.
do
end
+ update_user (a_user: CMS_USER)
+ -- Update user `a_user'.
+ do
+ end
+
feature -- Access: roles and permissions
user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
@@ -93,9 +98,13 @@ feature -- Change: roles and permissions
do
end
-
feature -- Access: node
+ nodes_count: INTEGER_64
+ -- Count of nodes.
+ do
+ end
+
nodes: LIST[CMS_NODE]
-- List of nodes.
do
@@ -156,11 +165,4 @@ feature -- Node
do
end
-feature -- User
-
- new_user (a_user: CMS_USER)
- -- Add a new user `a_user'.
- do
- end
-
end
diff --git a/library/src/persistence/cms_storage_sql.e b/library/src/persistence/cms_storage_sql.e
index b0266f1..e65b3bd 100644
--- a/library/src/persistence/cms_storage_sql.e
+++ b/library/src/persistence/cms_storage_sql.e
@@ -30,6 +30,58 @@ feature -- Execution
feature -- Operation
+ check_sql_query_validity (a_sql_statement: READABLE_STRING_8; a_params: detachable STRING_TABLE [detachable ANY])
+ local
+ l_sql_params: STRING_TABLE [READABLE_STRING_8]
+ i,j,n,m: INTEGER
+ s: STRING
+ do
+ create l_sql_params.make_caseless (0)
+ from
+ i := 1
+ n := a_sql_statement.count
+ until
+ i > n
+ loop
+ i := a_sql_statement.index_of (':', i)
+ if i = 0 then
+ i := n -- exit
+ else
+ from
+ j := i + 1
+ until
+ j > n or not (a_sql_statement[j].is_alpha_numeric or a_sql_statement[j] = '_')
+ loop
+ j := j + 1
+ end
+ s := a_sql_statement.substring (i + 1, j - 1)
+ l_sql_params.force (s, s)
+ end
+ i := i + 1
+ end
+ if a_params = Void then
+ if not l_sql_params.is_empty then
+ check False end
+ error_handler.add_custom_error (-1, "invalid query", "missing value for sql parameters")
+ end
+ else
+ across
+ a_params as ic
+ loop
+ if l_sql_params.has (ic.key) then
+ l_sql_params.remove (ic.key)
+ else
+ error_handler.add_custom_error (-1, "useless value", "value for unexpected parameter [" + ic.key + "]")
+ end
+ end
+ across
+ l_sql_params as ic
+ loop
+ error_handler.add_custom_error (-1, "invalid query", "missing value for sql parameter [" + ic.item + "]")
+ end
+ end
+ end
+
sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
deferred
end
@@ -45,6 +97,11 @@ feature -- Access
deferred
end
+ sql_start
+ -- Set the cursor on first element.
+ deferred
+ end
+
sql_after: BOOLEAN
-- Are there no more items to iterate over?
deferred
diff --git a/library/src/persistence/node/cms_node_storage.e b/library/src/persistence/node/cms_node_storage.e
index 4a42d95..d36733b 100644
--- a/library/src/persistence/node/cms_node_storage.e
+++ b/library/src/persistence/node/cms_node_storage.e
@@ -19,6 +19,11 @@ feature -- Error Handling
feature -- Access
+ nodes_count: INTEGER_64
+ -- Count of nodes.
+ deferred
+ end
+
nodes: LIST [CMS_NODE]
-- List of nodes.
deferred
@@ -49,7 +54,7 @@ feature -- Change: Node
-- Save node `a_node'.
require
no_id: not a_node.has_id
- valid_user: attached a_node.author as l_author implies l_author.id > 0
+ valid_user: attached a_node.author as l_author and then l_author.id > 0
deferred
end
diff --git a/library/src/persistence/node/cms_node_storage_sql.e b/library/src/persistence/node/cms_node_storage_sql.e
index 229f3a5..7ea177d 100644
--- a/library/src/persistence/node/cms_node_storage_sql.e
+++ b/library/src/persistence/node/cms_node_storage_sql.e
@@ -16,7 +16,19 @@ inherit
SHARED_LOGGER
-feature -- Access
+feature -- Access
+
+ nodes_count: INTEGER_64
+ -- 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_64 (1)
+ end
+ sql_post_execution
+ end
nodes: LIST [CMS_NODE]
-- List of nodes.
@@ -29,6 +41,7 @@ feature -- Access
from
sql_query (select_nodes, Void)
sql_post_execution
+ sql_start
until
sql_after
loop
@@ -56,6 +69,7 @@ feature -- Access
l_parameters.put (a_lower, "offset")
sql_query (select_recent_nodes, l_parameters)
sql_post_execution
+ sql_start
until
sql_after
loop
@@ -99,18 +113,6 @@ feature -- Access
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_64
-- Last insert node id.
do
@@ -137,16 +139,16 @@ feature -- Change: Node
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")
+ 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_id")
+ l_parameters.put (l_author.id, "author")
else
- l_parameters.put (0, "author_id")
+ l_parameters.put (0, "author")
end
sql_change (sql_insert_node, l_parameters)
sql_post_execution
@@ -167,10 +169,6 @@ feature -- Change: Node
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
@@ -178,25 +176,28 @@ feature -- Change: Node
-- Update node content `a_node'.
local
l_parameters: STRING_TABLE [detachable ANY]
+ now: DATE_TIME
do
+ create now.make_now_utc
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.publication_date, "publish")
+ l_parameters.put (now, "changed")
l_parameters.put (a_node.id, "id")
if attached a_node.author as l_author then
- l_parameters.put (l_author.id, "id")
- l_parameters.put (l_author.id, "editor")
+ l_parameters.put (l_author.id, "author")
else
- l_parameters.put (0, "id")
- l_parameters.put (0, "editor")
+ l_parameters.put (0, "author")
end
sql_change (sql_update_node, l_parameters)
sql_post_execution
+ if not error_handler.has_error then
+ a_node.set_modification_date (now)
+ end
end
update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
@@ -210,8 +211,8 @@ feature -- Change: Node
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_node_id, "id")
+ 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)
sql_post_execution
end
@@ -227,8 +228,8 @@ feature -- Change: Node
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_node_id, "id")
+ 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)
sql_post_execution
end
@@ -244,8 +245,8 @@ feature -- Change: Node
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_node_id, "id")
+ 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)
sql_post_execution
end
@@ -257,49 +258,36 @@ feature {NONE} -- Queries
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_node_by_id: STRING = "select * from Nodes where nid =:nid order by nid desc, publish desc;"
- Select_recent_nodes: STRING = "select * from Nodes order by id desc, publication_date desc LIMIT :rows OFFSET :offset ;"
+ Select_recent_nodes: STRING = "select * from Nodes order by nid desc, publish 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_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_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_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_Delete_node: STRING = "delete from nodes where id=:id;"
+ SQL_Delete_node: STRING = "delete from nodes where nid=:nid;"
- Sql_update_node_author: STRING = "update nodes SET author_id=:user_id where id=:id;"
+ Sql_update_node_author: STRING = "update nodes SET author=:author where nid=:nid;"
- Sql_last_insert_node_id: STRING = "SELECT MAX(id) from nodes;"
+ 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_summary: STRING ="update nodes SET summary=:summary, changed=:changed, version = version + 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_last_insert_node_id: STRING = "SELECT MAX(nid) 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_user_author: STRING = "SELECT * FROM Nodes INNER JOIN users ON nodes.author=users.uid and users.uid = :uid;"
- 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"
+ Select_node_author: STRING = "SELECT * FROM Users INNER JOIN nodes ON nodes.author=users.uid and nodes.nid =:nid;"
feature {NONE} -- Implementation
@@ -309,24 +297,27 @@ feature {NONE} -- Implementation
if attached sql_read_integer_64 (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
+ if attached sql_read_string_32 (4) as l_title then
Result.set_title (l_title)
end
- if attached sql_read_string_32 (6) as l_summary then
+ if attached sql_read_string_32 (5) as l_summary then
Result.set_summary (l_summary)
end
- if attached sql_read_string (7) as l_content then
+ 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 ...
+ end
end
fetch_author: detachable CMS_USER
diff --git a/library/src/persistence/user/cms_user_storage.e b/library/src/persistence/user/cms_user_storage.e
index 6bfc9a7..5d548dd 100644
--- a/library/src/persistence/user/cms_user_storage.e
+++ b/library/src/persistence/user/cms_user_storage.e
@@ -36,7 +36,7 @@ feature -- Access
deferred
ensure
same_id: Result /= Void implies Result.id = a_id
- password: Result /= Void implies Result.password /= Void
+ password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void)
end
user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
@@ -46,7 +46,7 @@ feature -- Access
deferred
ensure
same_name: Result /= Void implies a_name ~ Result.name
- password: Result /= Void implies Result.password /= Void
+ password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void)
end
user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
@@ -54,7 +54,7 @@ feature -- Access
deferred
ensure
same_email: Result /= Void implies a_email ~ Result.email
- password: Result /= Void implies Result.password /= Void
+ password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void)
end
is_valid_credential (a_u, a_p: READABLE_STRING_32): BOOLEAN
@@ -64,8 +64,17 @@ feature -- Access
feature -- Change: user
- save_user (a_user: CMS_USER)
+ new_user (a_user: CMS_USER)
+ -- New user `a_user'.
+ require
+ no_id: not a_user.has_id
+ deferred
+ end
+
+ update_user (a_user: CMS_USER)
-- Save user `a_user'.
+ require
+ has_id: a_user.has_id
deferred
end
diff --git a/library/src/persistence/user/cms_user_storage_sql.e b/library/src/persistence/user/cms_user_storage_sql.e
index a00d978..e6d20d6 100644
--- a/library/src/persistence/user/cms_user_storage_sql.e
+++ b/library/src/persistence/user/cms_user_storage_sql.e
@@ -47,6 +47,7 @@ feature -- Access: user
from
sql_query (select_users, Void)
sql_post_execution
+ sql_start
until
sql_after
loop
@@ -66,7 +67,7 @@ feature -- Access: user
error_handler.reset
log.write_information (generator + ".user")
create l_parameters.make (1)
- l_parameters.put (a_id, "id")
+ l_parameters.put (a_id, "uid")
sql_query (select_user_by_id, l_parameters)
if sql_rows_count = 1 then
Result := fetch_user
@@ -136,20 +137,81 @@ feature -- Access: user
feature -- Change: user
- save_user (a_user: CMS_USER)
+ 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
sql_begin_transaction
- new_user (a_user)
+ 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, "name")
+ l_parameters.put (l_password_hash, "password")
+ l_parameters.put (l_password_salt, "salt")
+ l_parameters.put (l_email, "email")
+ l_parameters.put (create {DATE_TIME}.make_now_utc, "created")
+
+ sql_change (sql_insert_user, l_parameters)
+ sql_post_execution
+ if not error_handler.has_error then
+ a_user.set_id (last_inserted_user_id)
+ sql_post_execution
+ end
sql_commit_transaction
else
- debug ("refactor_fixme")
- fixme ("maybe we should not always carry password, in this case, to implement the else part..")
- end
+ -- set error
+ error_handler.add_custom_error (-1, "bad request" , "Missing password or email")
+ end
+ end
+
+ update_user (a_user: CMS_USER)
+ -- Save user `a_user'.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ l_password_salt, l_password_hash: detachable READABLE_STRING_8
+ l_security: SECURITY_PROVIDER
+ do
+ if attached a_user.password as l_password then
+ -- New password!
+ create l_security
+ l_password_salt := l_security.salt
+ l_password_hash := l_security.password_hash (l_password, l_password_salt)
+ else
+ -- Existing hashed password
+ l_password_hash := a_user.hashed_password
+ l_password_salt := user_salt (a_user.name)
+ end
+ if
+ l_password_hash /= Void and l_password_salt /= Void and
+ attached a_user.email as l_email
+ then
+ error_handler.reset
+
+ log.write_information (generator + ".update_user")
+ create l_parameters.make (6)
+ l_parameters.put (a_user.id, "uid")
+ l_parameters.put (a_user.name, "name")
+ l_parameters.put (l_password_hash, "password")
+ l_parameters.put (l_password_salt, "salt")
+ l_parameters.put (l_email, "email")
+ l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
+
+ sql_change (sql_update_user, l_parameters)
+ sql_post_execution
+ else
+ -- set error
+ error_handler.add_custom_error (-1, "bad request" , "Missing password or email")
end
end
@@ -193,44 +255,6 @@ feature {NONE} -- Implementation
sql_post_execution
end
- new_user (a_user: CMS_USER)
- -- Add a new user `a_user'.
- require
- no_id: not a_user.has_id
- 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)
- sql_post_execution
- if not error_handler.has_error then
- a_user.set_id (last_inserted_user_id)
- sql_post_execution
- end
- 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
@@ -282,25 +306,27 @@ feature {NONE} -- Sql Queries: USER
Select_users_count: STRING = "select count(*) from Users;"
-- Number of users.
- Sql_last_insert_user_id: STRING = "SELECT MAX(id) from Users;"
+ Sql_last_insert_user_id: STRING = "SELECT MAX(uid) from Users;"
Select_users: STRING = "select * from Users;"
-- List of users.
- Select_user_by_id: STRING = "select * from Users where id =:id;"
+ 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 username =: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;"
-- Retrieve user by email if exists.
- Select_salt_by_username: STRING = "select salt from Users where username =: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 (username, password, salt, email) values (:username, :password, :salt, :email);"
- -- SQL Insert to add a new node.
+ 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;"
end
diff --git a/library/src/service/cms_api.e b/library/src/service/cms_api.e
index 75e26b3..1db79c3 100644
--- a/library/src/service/cms_api.e
+++ b/library/src/service/cms_api.e
@@ -88,12 +88,14 @@ feature -- Status Report
feature -- Access: Node
+ nodes_count: INTEGER_64
+ do
+ Result := storage.nodes_count
+ end
+
nodes: LIST [CMS_NODE]
-- List of nodes.
do
- debug ("refactor_fixme")
- fixme ("Implementation")
- end
Result := storage.nodes
end
@@ -174,12 +176,15 @@ feature -- Change User
new_user (a_user: CMS_USER)
-- Add a new user `a_user'.
+ require
+ no_id: not a_user.has_id
+ no_hashed_password: a_user.hashed_password = Void
do
if
attached a_user.password as l_password and then
attached a_user.email as l_email
then
- storage.save_user (a_user)
+ storage.new_user (a_user)
else
debug ("refactor_fixme")
fixme ("Add error")
@@ -187,6 +192,14 @@ feature -- Change User
end
end
+ update_user (a_user: CMS_USER)
+ -- Update user `a_user'.
+ require
+ has_id: a_user.has_id
+ do
+ storage.update_user (a_user)
+ end
+
feature -- Helpers
html_encoded (a_string: READABLE_STRING_GENERAL): STRING_8