Refactor directory structrue
This commit is contained in:
0
library/persistence/Readme.md
Normal file
0
library/persistence/Readme.md
Normal file
166
library/persistence/implementation/common/cms_storage_null.e
Normal file
166
library/persistence/implementation/common/cms_storage_null.e
Normal file
@@ -0,0 +1,166 @@
|
||||
note
|
||||
description: "Summary description for {CMS_STORAGE_NULL}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_STORAGE_NULL
|
||||
|
||||
inherit
|
||||
|
||||
CMS_STORAGE
|
||||
redefine
|
||||
default_create
|
||||
select
|
||||
default_create
|
||||
end
|
||||
REFACTORING_HELPER
|
||||
rename
|
||||
default_create as default_create_rh
|
||||
end
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
create error_handler.make
|
||||
end
|
||||
|
||||
feature -- Access: user
|
||||
|
||||
has_user: BOOLEAN
|
||||
-- Has any user?
|
||||
do
|
||||
end
|
||||
|
||||
all_users: LIST [CMS_USER]
|
||||
do
|
||||
create {ARRAYED_LIST[CMS_USER]} Result.make (0)
|
||||
end
|
||||
|
||||
user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
|
||||
do
|
||||
end
|
||||
|
||||
user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
|
||||
do
|
||||
end
|
||||
|
||||
user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
|
||||
do
|
||||
end
|
||||
|
||||
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
||||
do
|
||||
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)
|
||||
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)
|
||||
end
|
||||
|
||||
feature -- Change: user
|
||||
|
||||
save_user (a_user: CMS_USER)
|
||||
-- Add a new 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
|
||||
do
|
||||
end
|
||||
|
||||
user_roles: LIST [CMS_USER_ROLE]
|
||||
do
|
||||
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
|
||||
end
|
||||
|
||||
|
||||
feature -- Access: node
|
||||
|
||||
nodes: LIST[CMS_NODE]
|
||||
-- List of nodes.
|
||||
do
|
||||
create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
|
||||
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)
|
||||
end
|
||||
|
||||
node (a_id: INTEGER_64): detachable CMS_NODE
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
|
||||
-- Node's author. if any.
|
||||
do
|
||||
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)
|
||||
end
|
||||
|
||||
feature -- Node
|
||||
|
||||
save_node (a_node: CMS_NODE)
|
||||
-- Add a new node
|
||||
do
|
||||
end
|
||||
|
||||
delete_node (a_id: INTEGER_64)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
update_node (a_id: like {CMS_NODE}.id; a_node: CMS_NODE)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
update_node_title (a_id: like {CMS_NODE}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
update_node_summary (a_id: like {CMS_NODE}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
update_node_content (a_id: like {CMS_NODE}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- User
|
||||
|
||||
new_user (a_user: CMS_USER)
|
||||
-- Add a new user `a_user'.
|
||||
do
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,29 @@
|
||||
note
|
||||
description: "Database configuration"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
deferred class
|
||||
DATABASE_CONFIG
|
||||
|
||||
feature -- Database access
|
||||
|
||||
hostname: STRING = ""
|
||||
-- Database hostname.
|
||||
|
||||
username: STRING = ""
|
||||
-- Database username.
|
||||
|
||||
password: STRING = ""
|
||||
-- Database password.
|
||||
|
||||
database_name: STRING = "EiffelDB"
|
||||
-- Database name.
|
||||
|
||||
is_keep_connection: BOOLEAN
|
||||
-- Keep Connection to database?
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,191 @@
|
||||
note
|
||||
description: "Abstract class to handle a database connection"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
deferred class
|
||||
DATABASE_CONNECTION
|
||||
|
||||
inherit
|
||||
|
||||
DATABASE_CONFIG
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_common
|
||||
-- Create a database handler with common settings.
|
||||
deferred
|
||||
ensure
|
||||
db_application_not_void: db_application /= Void
|
||||
db_control_not_void: db_control /= Void
|
||||
end
|
||||
|
||||
make_basic ( a_database_name: STRING)
|
||||
-- Create a database handler with common settings and
|
||||
-- set database_name with `a_database_name'.
|
||||
require
|
||||
database_name_not_void: a_database_name /= Void
|
||||
database_name_not_empty: not a_database_name.is_empty
|
||||
deferred
|
||||
ensure
|
||||
db_application_not_void: db_application /= Void
|
||||
db_control_not_void: db_control /= Void
|
||||
end
|
||||
|
||||
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
|
||||
|
||||
-- Create a database handler with user `a_username', password `a_password',
|
||||
-- host `a_hostname', database_name `a_database_name', and keep_connection `connection'.
|
||||
require
|
||||
username_not_void: a_username /= Void
|
||||
username_not_empty: not a_username.is_empty
|
||||
password_not_void: a_password /= Void
|
||||
hostname_not_void: a_hostname /= Void
|
||||
hotname_not_empty: not a_hostname.is_empty
|
||||
database_name_not_void: a_database_name /= Void
|
||||
database_name_not_empty: not a_database_name.is_empty
|
||||
deferred
|
||||
ensure
|
||||
db_application_not_void: db_application /= Void
|
||||
db_control_not_void: db_control /= Void
|
||||
end
|
||||
|
||||
login_with_connection_string (a_connection_string: STRING)
|
||||
-- Login with `a_connection_string'
|
||||
-- and immediately connect to database.
|
||||
deferred
|
||||
ensure
|
||||
db_application_not_void: db_application /= Void
|
||||
db_control_not_void: db_control /= Void
|
||||
end
|
||||
|
||||
feature -- Database Setup
|
||||
|
||||
db_application: DATABASE_APPL [DATABASE]
|
||||
-- Database application.
|
||||
|
||||
db_control: DB_CONTROL
|
||||
-- Database control.
|
||||
|
||||
keep_connection: BOOLEAN
|
||||
-- Keep connection alive?
|
||||
|
||||
feature -- Transactions
|
||||
|
||||
begin_transaction
|
||||
-- Start a transaction which will be terminated by a call to `rollback' or `commit'.
|
||||
local
|
||||
rescued: BOOLEAN
|
||||
do
|
||||
if not rescued then
|
||||
if db_control.is_ok then
|
||||
db_control.begin
|
||||
else
|
||||
database_error_handler.add_database_error (db_control.error_message_32, db_control.error_code)
|
||||
end
|
||||
end
|
||||
rescue
|
||||
rescued := True
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
db_control.reset
|
||||
retry
|
||||
end
|
||||
|
||||
commit
|
||||
-- Commit updates in the database.
|
||||
local
|
||||
rescued: BOOLEAN
|
||||
do
|
||||
if not rescued then
|
||||
if db_control.is_ok then
|
||||
db_control.commit
|
||||
else
|
||||
database_error_handler.add_database_error (db_control.error_message_32, db_control.error_code)
|
||||
end
|
||||
end
|
||||
rescue
|
||||
rescued := True
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
db_control.reset
|
||||
retry
|
||||
end
|
||||
|
||||
rollback
|
||||
-- Rollback updates in the database.
|
||||
local
|
||||
rescued: BOOLEAN
|
||||
do
|
||||
if not rescued then
|
||||
if db_control.is_ok then
|
||||
db_control.rollback
|
||||
else
|
||||
database_error_handler.add_database_error (db_control.error_message_32, db_control.error_code)
|
||||
end
|
||||
end
|
||||
rescue
|
||||
rescued := True
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
db_control.reset
|
||||
retry
|
||||
end
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
not_keep_connection
|
||||
do
|
||||
keep_connection := False
|
||||
end
|
||||
|
||||
feature -- Conection
|
||||
|
||||
connect
|
||||
-- Connect to the database.
|
||||
require else
|
||||
db_control_not_void: db_control /= Void
|
||||
do
|
||||
if not is_connected then
|
||||
db_control.connect
|
||||
end
|
||||
end
|
||||
|
||||
disconnect
|
||||
-- Disconnect from the database.
|
||||
require else
|
||||
db_control_not_void: db_control /= Void
|
||||
do
|
||||
db_control.disconnect
|
||||
end
|
||||
|
||||
is_connected: BOOLEAN
|
||||
-- True if connected to the database.
|
||||
require else
|
||||
db_control_not_void: db_control /= Void
|
||||
do
|
||||
Result := db_control.is_connected
|
||||
end
|
||||
|
||||
feature -- Error Handling
|
||||
|
||||
database_error_handler: DATABASE_ERROR_HANDLER
|
||||
-- Error handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- Has error?
|
||||
do
|
||||
Result := database_error_handler.has_error
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception)
|
||||
-- Record exception as an error.
|
||||
do
|
||||
if attached a_e as l_e and then attached l_e.trace as l_trace then
|
||||
database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
note
|
||||
description: "Null object to meet Void Safe."
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_CONNECTION_NULL
|
||||
|
||||
inherit
|
||||
|
||||
DATABASE_CONNECTION
|
||||
redefine
|
||||
db_application,
|
||||
is_connected
|
||||
end
|
||||
|
||||
create
|
||||
make, make_common, make_basic
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make_common
|
||||
-- Create a database handler for ODBC with common settings.
|
||||
do
|
||||
create database_error_handler.make
|
||||
create db_application.login (username, password)
|
||||
db_application.set_hostname (hostname)
|
||||
db_application.set_data_source (database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
end
|
||||
|
||||
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
|
||||
|
||||
-- Create a database handler for ODBC.
|
||||
do
|
||||
make_common
|
||||
end
|
||||
|
||||
make_basic (a_database_name: STRING)
|
||||
|
||||
-- Create a database handler for ODBC.
|
||||
do
|
||||
make_common
|
||||
end
|
||||
|
||||
|
||||
login_with_connection_string (a_string: STRING)
|
||||
-- Login with `a_connection_string'
|
||||
-- and immediately connect to database.
|
||||
do
|
||||
make_common
|
||||
end
|
||||
|
||||
|
||||
feature -- Databse Connection
|
||||
|
||||
db_application: DATABASE_APPL[DATABASE_NULL]
|
||||
-- Database application.
|
||||
|
||||
|
||||
is_connected: BOOLEAN
|
||||
-- True if connected to the database.
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,126 @@
|
||||
note
|
||||
description: "Object that handle a database connection for ODBC"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_CONNECTION_ODBC
|
||||
|
||||
inherit
|
||||
|
||||
DATABASE_CONNECTION
|
||||
redefine
|
||||
db_application
|
||||
end
|
||||
|
||||
create
|
||||
make, make_common, make_basic, login_with_connection_string
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make_common
|
||||
-- Create a database handler for ODBC with common settings.
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
create db_application.login (username, password)
|
||||
|
||||
if not l_retried then
|
||||
db_application.set_hostname (hostname)
|
||||
db_application.set_data_source (database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
set_successful
|
||||
else
|
||||
create db_control.make
|
||||
end
|
||||
rescue
|
||||
create db_control.make
|
||||
set_last_error_from_exception ("Connection execution")
|
||||
log.write_critical (generator + ".make_common:" + last_error_message)
|
||||
if is_connected then
|
||||
disconnect
|
||||
end
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
make_basic (a_database_name: STRING)
|
||||
-- Create a database handler and
|
||||
-- set database_name to `a_database_name'.
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
create db_application.login (username, password)
|
||||
|
||||
if not l_retried then
|
||||
db_application.set_hostname (hostname)
|
||||
db_application.set_data_source (a_database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
set_successful
|
||||
else
|
||||
create db_control.make
|
||||
end
|
||||
rescue
|
||||
create db_control.make
|
||||
set_last_error_from_exception ("Connection execution")
|
||||
log.write_critical (generator + ".make_common:" + last_error_message)
|
||||
if is_connected then
|
||||
disconnect
|
||||
end
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
|
||||
|
||||
-- Create a database handler for ODBC and set `username' to `a_username',
|
||||
-- `password' to `a_password'
|
||||
-- `database_name' to `a_database_name'
|
||||
-- `connection' to `a_connection'
|
||||
do
|
||||
create db_application.login (a_username, a_password)
|
||||
db_application.set_hostname (a_hostname)
|
||||
db_application.set_data_source (a_database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
end
|
||||
|
||||
login_with_connection_string (a_string: STRING)
|
||||
-- Login with `a_connection_string'and immediately connect to database.
|
||||
do
|
||||
log.write_debug (generator +".login_with_connection_string")
|
||||
create db_application.login_with_connection_string (a_string)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
log.write_debug (generator +".login_with_connection_string, is_keep_connection? "+ is_keep_connection.out )
|
||||
keep_connection := is_keep_connection
|
||||
if keep_connection then
|
||||
connect
|
||||
if not db_control.is_ok then
|
||||
log.write_critical (generator +".login_with_connection_string:"+ db_control.error_code.out )
|
||||
log.write_critical (generator +".login_with_connection_string:"+ db_control.error_message_32 )
|
||||
end
|
||||
log.write_debug (generator +".login_with_connection_string, After connect, is_connected? "+ is_connected.out)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Databse Connection
|
||||
|
||||
db_application: DATABASE_APPL [ODBC]
|
||||
-- Database application.
|
||||
|
||||
end
|
||||
@@ -0,0 +1,237 @@
|
||||
note
|
||||
description: "Abstract Database Handler"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
deferred class
|
||||
DATABASE_HANDLER
|
||||
|
||||
inherit
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
feature -- Access
|
||||
|
||||
store: detachable DATABASE_STORE_PROCEDURE
|
||||
-- Database stored_procedure to handle.
|
||||
|
||||
query: detachable DATABASE_QUERY
|
||||
-- Database query.
|
||||
|
||||
feature -- Modifiers
|
||||
|
||||
set_store (a_store: DATABASE_STORE_PROCEDURE)
|
||||
-- Set `store' to `a_store' to execute.
|
||||
require
|
||||
store_not_void: a_store /= Void
|
||||
do
|
||||
store := a_store
|
||||
ensure
|
||||
store_set: store = a_store
|
||||
end
|
||||
|
||||
set_query (a_query: DATABASE_QUERY)
|
||||
-- Set `query' to `a_query' to execute.
|
||||
require
|
||||
query_not_void: a_query /= Void
|
||||
do
|
||||
query := a_query
|
||||
ensure
|
||||
query_set: query = a_query
|
||||
end
|
||||
|
||||
feature -- Functionality Store Procedures
|
||||
|
||||
execute_store_reader
|
||||
-- Execute a `store' to read data.
|
||||
require
|
||||
store_not_void: store /= void
|
||||
deferred
|
||||
end
|
||||
|
||||
execute_store_writer
|
||||
-- Execute a `store' to write data.
|
||||
require
|
||||
store_not_void: store /= void
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- SQL Queries
|
||||
|
||||
execute_query
|
||||
-- Execute sql query, the read data from the database.
|
||||
require
|
||||
query_not_void: query /= void
|
||||
deferred
|
||||
end
|
||||
|
||||
execute_change
|
||||
-- Execute sql query that update/add data.
|
||||
require
|
||||
query_not_void: query /= void
|
||||
deferred
|
||||
end
|
||||
|
||||
|
||||
feature -- Iteration
|
||||
|
||||
start
|
||||
-- Set the cursor on first element.
|
||||
deferred
|
||||
end
|
||||
|
||||
item: ANY
|
||||
-- Item at current cursor position.
|
||||
require
|
||||
valid_position: not after
|
||||
deferred
|
||||
end
|
||||
|
||||
after: BOOLEAN
|
||||
-- Are there no more items to iterate over?
|
||||
deferred
|
||||
end
|
||||
|
||||
forth
|
||||
-- Move to next position.
|
||||
require
|
||||
valid_position: not after
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
read_integer_32 (a_index: INTEGER): INTEGER_32
|
||||
-- Retrieved value at `a_index' position in `item'.
|
||||
do
|
||||
if attached {DB_TUPLE} item as l_item then
|
||||
if attached {INTEGER_32_REF} l_item.item (a_index) as ll_item then
|
||||
Result := ll_item.item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
read_string (a_index: INTEGER): detachable STRING
|
||||
-- Retrieved value at `a_index' position in `item'.
|
||||
do
|
||||
if attached {DB_TUPLE} item as l_item then
|
||||
if attached {STRING} l_item.item (a_index) as ll_item then
|
||||
Result := ll_item
|
||||
elseif attached {BOOLEAN_REF} l_item.item (a_index) as ll_item then
|
||||
Result := ll_item.item.out
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
read_date_time (a_index: INTEGER): detachable DATE_TIME
|
||||
-- Retrieved value at `a_index' position in `item'.
|
||||
do
|
||||
if attached {DB_TUPLE} item as l_item then
|
||||
if attached {DATE_TIME} l_item.item (a_index) as ll_item then
|
||||
Result := ll_item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
read_boolean (a_index: INTEGER): detachable BOOLEAN
|
||||
-- Retrieved value at `a_index' position in `item'.
|
||||
do
|
||||
if attached {DB_TUPLE} item as l_item then
|
||||
if attached {BOOLEAN} l_item.item (a_index) as ll_item then
|
||||
Result := ll_item
|
||||
elseif attached {BOOLEAN_REF} l_item.item (a_index) as ll_item then
|
||||
Result := ll_item.item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
count: INTEGER
|
||||
-- Number of rows, last execution.
|
||||
deferred
|
||||
end
|
||||
|
||||
connection: DATABASE_CONNECTION
|
||||
-- Database connection.
|
||||
|
||||
db_control: DB_CONTROL
|
||||
-- Database control.
|
||||
do
|
||||
Result := connection.db_control
|
||||
end
|
||||
|
||||
db_result: detachable DB_RESULT
|
||||
-- Database query result.
|
||||
|
||||
db_selection: detachable DB_SELECTION
|
||||
-- Database selection.
|
||||
|
||||
db_change: detachable DB_CHANGE
|
||||
-- Database modification.
|
||||
|
||||
feature -- Error handling
|
||||
|
||||
check_database_change_error
|
||||
-- Check database error from `db_change'.
|
||||
do
|
||||
if attached db_change as l_change and then not l_change.is_ok then
|
||||
database_error_handler.add_database_error (l_change.error_message_32, l_change.error_code)
|
||||
log.write_error (generator + ".check_database_change_error: " + l_change.error_message_32)
|
||||
l_change.reset
|
||||
end
|
||||
end
|
||||
|
||||
check_database_selection_error
|
||||
-- Check database error from `db_selection'.
|
||||
do
|
||||
if attached db_selection as l_selection and then not l_selection.is_ok then
|
||||
database_error_handler.add_database_error (l_selection.error_message_32, l_selection.error_code)
|
||||
log.write_error (generator + ".check_database_selection_error: " + l_selection.error_message_32)
|
||||
l_selection.reset
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Error Handling
|
||||
|
||||
database_error_handler: DATABASE_ERROR_HANDLER
|
||||
-- Error handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- Has error?
|
||||
do
|
||||
Result := database_error_handler.has_error
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception)
|
||||
-- Record exception as an error.
|
||||
do
|
||||
if attached a_e as l_e and then attached l_e.trace as l_trace then
|
||||
database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Connection Handling
|
||||
|
||||
connect
|
||||
-- Connect to the database.
|
||||
deferred
|
||||
end
|
||||
|
||||
disconnect
|
||||
-- Disconnect from the database.
|
||||
deferred
|
||||
ensure
|
||||
not_connected: not is_connected
|
||||
end
|
||||
|
||||
is_connected: BOOLEAN
|
||||
-- True if connected to the database.
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,234 @@
|
||||
note
|
||||
description: "Database handler Implementation"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_HANDLER_IMPL
|
||||
|
||||
inherit
|
||||
DATABASE_HANDLER
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_connection: DATABASE_CONNECTION)
|
||||
-- Create a database handler with connnection `connection'.
|
||||
do
|
||||
connection := a_connection
|
||||
create last_query.make_now
|
||||
create database_error_handler.make
|
||||
ensure
|
||||
connection_not_void: connection /= Void
|
||||
last_query_not_void: last_query /= Void
|
||||
database_error_handler_set: attached database_error_handler
|
||||
end
|
||||
|
||||
feature -- Functionality
|
||||
|
||||
execute_store_reader
|
||||
-- Execute stored procedure that returns data.
|
||||
local
|
||||
l_db_selection: DB_SELECTION
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
if not l_retried then
|
||||
database_error_handler.reset
|
||||
if attached store as l_store then
|
||||
create l_db_selection.make
|
||||
db_selection := l_db_selection
|
||||
items := l_store.execute_reader (l_db_selection)
|
||||
check_database_selection_error
|
||||
end
|
||||
log.write_debug ( generator+".execute_reader Successful")
|
||||
end
|
||||
rescue
|
||||
l_retried := True
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
if attached db_selection as l_selection then
|
||||
l_selection.reset
|
||||
end
|
||||
retry
|
||||
end
|
||||
|
||||
execute_store_writer
|
||||
-- Execute stored procedure that update/add data.
|
||||
local
|
||||
l_db_change: DB_CHANGE
|
||||
l_retried : BOOLEAN
|
||||
do
|
||||
if not l_retried then
|
||||
database_error_handler.reset
|
||||
if attached store as l_store then
|
||||
create l_db_change.make
|
||||
db_change := l_db_change
|
||||
l_store.execute_writer (l_db_change)
|
||||
check_database_change_error
|
||||
end
|
||||
log.write_debug ( generator+".execute_writer Successful")
|
||||
end
|
||||
rescue
|
||||
l_retried := True
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
if attached db_change as l_change then
|
||||
l_change.reset
|
||||
end
|
||||
retry
|
||||
end
|
||||
|
||||
feature -- SQL Queries
|
||||
|
||||
execute_query
|
||||
-- Execute query.
|
||||
local
|
||||
l_db_selection: DB_SELECTION
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
if not l_retried then
|
||||
database_error_handler.reset
|
||||
if attached query as l_query then
|
||||
create l_db_selection.make
|
||||
db_selection := l_db_selection
|
||||
items := l_query.execute_reader (l_db_selection)
|
||||
check_database_selection_error
|
||||
end
|
||||
end
|
||||
rescue
|
||||
l_retried := True
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
if attached db_selection as l_selection then
|
||||
l_selection.reset
|
||||
end
|
||||
retry
|
||||
end
|
||||
|
||||
|
||||
execute_change
|
||||
-- Execute sql_query that update/add data.
|
||||
local
|
||||
l_db_change: DB_CHANGE
|
||||
l_retried : BOOLEAN
|
||||
do
|
||||
if not l_retried then
|
||||
database_error_handler.reset
|
||||
if attached query as l_query then
|
||||
create l_db_change.make
|
||||
db_change := l_db_change
|
||||
l_query.execute_change (l_db_change)
|
||||
check_database_change_error
|
||||
end
|
||||
end
|
||||
rescue
|
||||
l_retried := True
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
if attached db_change as l_change then
|
||||
l_change.reset
|
||||
end
|
||||
retry
|
||||
end
|
||||
|
||||
|
||||
feature -- Iteration
|
||||
|
||||
start
|
||||
-- Set the cursor on first element.
|
||||
do
|
||||
if attached db_selection as l_db_selection and then l_db_selection.container /= Void then
|
||||
l_db_selection.start
|
||||
end
|
||||
end
|
||||
|
||||
forth
|
||||
-- Move cursor to next element.
|
||||
do
|
||||
if attached db_selection as l_db_selection then
|
||||
l_db_selection.forth
|
||||
else
|
||||
check False end
|
||||
end
|
||||
end
|
||||
|
||||
after: BOOLEAN
|
||||
-- True for the last element.
|
||||
do
|
||||
if attached db_selection as l_db_selection and then l_db_selection.container /= Void then
|
||||
Result := l_db_selection.after or else l_db_selection.cursor = Void
|
||||
else
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
|
||||
item: DB_TUPLE
|
||||
-- Current element.
|
||||
do
|
||||
if attached db_selection as l_db_selection and then attached l_db_selection.cursor as l_cursor then
|
||||
create {DB_TUPLE} Result.copy (l_cursor)
|
||||
else
|
||||
check False then end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
last_query: DATE_TIME
|
||||
-- Last time when a query was executed.
|
||||
|
||||
keep_connection: BOOLEAN
|
||||
-- Keep connection alive?
|
||||
do
|
||||
Result := connection.keep_connection
|
||||
end
|
||||
|
||||
connect
|
||||
-- Connect to the database.
|
||||
require else
|
||||
db_control_not_void: db_control /= Void
|
||||
do
|
||||
if not is_connected then
|
||||
db_control.connect
|
||||
end
|
||||
end
|
||||
|
||||
disconnect
|
||||
-- Disconnect from the database.
|
||||
require else
|
||||
db_control_not_void: db_control /= Void
|
||||
do
|
||||
db_control.disconnect
|
||||
end
|
||||
|
||||
is_connected: BOOLEAN
|
||||
-- True if connected to the database.
|
||||
require else
|
||||
db_control_not_void: db_control /= Void
|
||||
do
|
||||
Result := db_control.is_connected
|
||||
end
|
||||
|
||||
affected_row_count: INTEGER
|
||||
-- The number of rows changed, deleted, or inserted by the last statement.
|
||||
do
|
||||
if attached db_change as l_update then
|
||||
Result := l_update.affected_row_count
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Result
|
||||
|
||||
items : detachable LIST[DB_RESULT]
|
||||
-- Query result.
|
||||
|
||||
count: INTEGER
|
||||
-- <Precursor>
|
||||
do
|
||||
if attached items as l_items then
|
||||
Result := l_items.count
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,91 @@
|
||||
note
|
||||
description: "External iteration cursor for {DATABASE_HANDLER}"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_ITERATION_CURSOR [G]
|
||||
|
||||
inherit
|
||||
|
||||
ITERATION_CURSOR [G]
|
||||
|
||||
ITERABLE [G]
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (a_handler: DATABASE_HANDLER; a_action: like action)
|
||||
-- Create an iterator and set `db_handlet' to `a_handler'
|
||||
-- `action' to `a_action'
|
||||
do
|
||||
db_handler := a_handler
|
||||
action := a_action
|
||||
ensure
|
||||
db_handler_set: db_handler = a_handler
|
||||
action_set: action = a_action
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
item: G
|
||||
-- Item at current cursor position.
|
||||
do
|
||||
Result := action.item ([db_item])
|
||||
end
|
||||
|
||||
db_item: DB_TUPLE
|
||||
-- Current element.
|
||||
do
|
||||
if attached {DB_TUPLE} db_handler.item as l_item then
|
||||
Result := l_item
|
||||
else
|
||||
check False then
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
after: BOOLEAN
|
||||
-- Are there no more items to iterate over?
|
||||
do
|
||||
Result := db_handler.after
|
||||
end
|
||||
|
||||
feature -- Cursor movement
|
||||
|
||||
start
|
||||
-- Set the cursor on first element.
|
||||
do
|
||||
db_handler.start
|
||||
end
|
||||
|
||||
forth
|
||||
-- Move to next position.
|
||||
do
|
||||
db_handler.forth
|
||||
end
|
||||
|
||||
feature -- Cursor
|
||||
|
||||
new_cursor: DATABASE_ITERATION_CURSOR [G]
|
||||
-- <Precursor>
|
||||
do
|
||||
Result := twin
|
||||
Result.start
|
||||
end
|
||||
|
||||
feature -- Action
|
||||
|
||||
action: FUNCTION [ANY, detachable TUPLE, G]
|
||||
-- Agent to create a new item of type G.
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Associated handler used for iteration.
|
||||
|
||||
end
|
||||
@@ -0,0 +1,539 @@
|
||||
note
|
||||
description: "Null object to meet void safe"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_NULL
|
||||
|
||||
inherit
|
||||
DATABASE
|
||||
|
||||
|
||||
feature -- Acccess
|
||||
|
||||
database_handle_name: STRING = "NULL"
|
||||
-- Handle name
|
||||
|
||||
feature -- For DATABASE_STATUS
|
||||
|
||||
is_error_updated: BOOLEAN
|
||||
-- Has an NULL function been called since last update which may have
|
||||
-- updated error code, error message?
|
||||
|
||||
is_warning_updated: BOOLEAN
|
||||
-- Has an ODBC function been called since last update which may have
|
||||
-- updated warning message?
|
||||
|
||||
found: BOOLEAN
|
||||
-- Is there any record matching the last
|
||||
-- selection condition used ?
|
||||
|
||||
clear_error
|
||||
-- Reset database error status.
|
||||
do
|
||||
end
|
||||
|
||||
insert_auto_identity_column: BOOLEAN = False
|
||||
-- For INSERTs and UPDATEs should table auto-increment identity columns be explicitly included in the statement?
|
||||
|
||||
feature -- For DATABASE_CHANGE
|
||||
|
||||
descriptor_is_available: BOOLEAN
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
feature -- For DATABASE_FORMAT
|
||||
|
||||
date_to_str (object: DATE_TIME): STRING
|
||||
-- String representation in SQL of `object'
|
||||
-- For ODBC, ORACLE
|
||||
do
|
||||
create Result.make_empty
|
||||
end
|
||||
|
||||
string_format (object: detachable STRING): STRING
|
||||
-- String representation in SQL of `object'
|
||||
obsolete
|
||||
"Use `string_format_32' instead."
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
string_format_32 (object: detachable READABLE_STRING_GENERAL): STRING_32
|
||||
-- String representation in SQL of `object'
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
True_representation: STRING
|
||||
-- Database representation of the boolean True
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
False_representation: STRING
|
||||
-- Database representation of the boolean False
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- For DATABASE_SELECTION, DATABASE_CHANGE
|
||||
|
||||
normal_parse: BOOLEAN
|
||||
-- Should the SQL string be normal parsed,
|
||||
-- using SQL_SCAN?
|
||||
do
|
||||
end
|
||||
|
||||
feature -- DATABASE_STRING
|
||||
|
||||
sql_name_string: STRING
|
||||
-- SQL type name of string
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- DATABASE_REAL
|
||||
|
||||
sql_name_real: STRING
|
||||
-- SQL type name for real
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- DATABASE_DATETIME
|
||||
|
||||
sql_name_datetime: STRING
|
||||
-- SQL type name for datetime
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- DATABASE_DECIMAL
|
||||
|
||||
sql_name_decimal: STRING
|
||||
-- SQL type name for decimal
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- DATABASE_DOUBLE
|
||||
|
||||
sql_name_double: STRING
|
||||
-- SQL type name for double
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- DATABASE_CHARACTER
|
||||
|
||||
sql_name_character: STRING
|
||||
-- SQL type name for character
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
feature -- DATABASE_INTEGER
|
||||
|
||||
sql_name_integer: STRING
|
||||
-- SQL type name for integer
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_name_integer_16: STRING
|
||||
-- SQL type name for integer
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_name_integer_64: STRING
|
||||
-- SQL type name for integer
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
feature -- DATABASE_BOOLEAN
|
||||
|
||||
sql_name_boolean: STRING
|
||||
-- SQL type name for boolean
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- LOGIN and DATABASE_APPL only for password_ok
|
||||
|
||||
|
||||
password_ok (upasswd: STRING): BOOLEAN
|
||||
-- Can the user password be Void?
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
password_ensure (name, passwd, uname, upasswd: STRING): BOOLEAN
|
||||
-- Is name equal to uname and passwd equal to upasswd?
|
||||
do
|
||||
end
|
||||
|
||||
feature -- For DATABASE_PROC
|
||||
|
||||
|
||||
support_sql_of_proc: BOOLEAN
|
||||
-- Does the database support SQL attachment to the stored procedure?
|
||||
do
|
||||
end
|
||||
|
||||
support_stored_proc: BOOLEAN
|
||||
-- Does the database support creating a stored procedure?
|
||||
do
|
||||
end
|
||||
|
||||
sql_as: STRING
|
||||
-- Creating a stored procedure "as"...
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_end: STRING
|
||||
-- End of the stored procedure creation string.
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_execution: STRING
|
||||
-- Begining of the stored procedure execution string.
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_creation: STRING
|
||||
-- Begining of the stored procedure creation string.
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_after_exec: STRING
|
||||
-- End of the stored procedure execution string.
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
support_drop_proc: BOOLEAN
|
||||
-- Does the database support stored procedure dropping from server?
|
||||
do
|
||||
end
|
||||
|
||||
name_proc_lower: BOOLEAN
|
||||
-- Has the name of the stored procedure to be in lower case?
|
||||
do
|
||||
end
|
||||
|
||||
map_var_between: STRING
|
||||
-- @ symbol for ODBC and Sybase
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
map_var_name_32 (par_name: READABLE_STRING_GENERAL): STRING_32
|
||||
-- Redefined for Sybase
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
Select_text_32 (proc_name: READABLE_STRING_GENERAL): STRING_32
|
||||
-- SQL query to get stored procedure text
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
Select_exists_32 (name: READABLE_STRING_GENERAL): STRING_32
|
||||
-- SQL query to test stored procedure existing
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
|
||||
Selection_string (rep_qualifier, rep_owner, repository_name: STRING): STRING
|
||||
-- String to select the table needed
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_string: STRING
|
||||
-- Database type of a string
|
||||
-- with a size less than Max_char_size
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_string2 (int: INTEGER): STRING
|
||||
-- Database type of a string
|
||||
-- with a size more than Max_char_size
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_wstring: STRING
|
||||
-- Database type of a string
|
||||
-- with a size less than Max_char_size
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
sql_wstring2 (int: INTEGER): STRING
|
||||
-- Database type of a string
|
||||
-- with a size more than Max_char_size
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
feature -- External features
|
||||
|
||||
get_error_message: POINTER
|
||||
-- Function related with the error processing
|
||||
do
|
||||
create Result
|
||||
end
|
||||
|
||||
get_error_message_string: STRING_32
|
||||
-- Function related with the error processing
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
get_error_code: INTEGER
|
||||
-- Function related with the error processing
|
||||
do
|
||||
end
|
||||
|
||||
get_warn_message: POINTER
|
||||
-- Function related with the error processing
|
||||
do
|
||||
create Result
|
||||
end
|
||||
|
||||
get_warn_message_string: STRING_32
|
||||
-- Function related with the error processing
|
||||
do
|
||||
Result := ""
|
||||
end
|
||||
|
||||
new_descriptor: INTEGER
|
||||
-- A descriptor is used to store a row fetched by FETCH command
|
||||
-- Whenever perform a SELECT statement, allocate a new descriptor
|
||||
-- by int_new_descriptor(), the descriptor is freed
|
||||
-- when the SELECT statement terminates.
|
||||
do
|
||||
end
|
||||
|
||||
init_order (no_descriptor: INTEGER; command: READABLE_STRING_GENERAL)
|
||||
-- In DYNAMICALLY EXECUTE mode perform the SQL statement
|
||||
-- But this routine only get things ready for dynamic execution:
|
||||
-- 1. get the SQL statement PREPAREd; and check if there are
|
||||
-- warning message for the SQL statement;
|
||||
-- 2. DESCRIBE the SQL statement and get enough information to
|
||||
-- allocate enough memory space for the corresponding descriptor.
|
||||
do
|
||||
end
|
||||
|
||||
start_order (no_descriptor: INTEGER)
|
||||
-- Finish execution of a SQL statement in DYNAMICLLY EXECUTION mode: */
|
||||
-- 1. if the PREPAREd SQL statement is a NON_SELECT statement,
|
||||
-- just EXECUTE it; otherwise, DEFINE a CURSOR for it and
|
||||
-- OPEN the CURSOR. In the process, if error occurs, do some
|
||||
-- clearence;
|
||||
do
|
||||
end
|
||||
|
||||
next_row (no_descriptor: INTEGER)
|
||||
-- A SELECT statement is now being executed in DYNAMIC EXECUTION mode,
|
||||
-- the routine is to FETCH a new tuple from database
|
||||
-- and if a new tuple is fetched, return 1 otherwise return 0.
|
||||
do
|
||||
end
|
||||
|
||||
terminate_order (no_descriptor: INTEGER)
|
||||
-- A SQL has been performed in DYNAMIC EXECUTION mode,
|
||||
-- so the routine is to do some clearence:
|
||||
-- 1. if the DYNAMICALLY EXECUTED SQL statement is a NON_SELECT
|
||||
-- statement, just free the memory for ODBCSQLDA and clear
|
||||
-- the cell in 'descriptor' to NULL; otherwise, CLOSE the CURSOR
|
||||
-- and then do the same clearence.
|
||||
-- 2. return error number.
|
||||
do
|
||||
end
|
||||
|
||||
close_cursor (no_descriptor: INTEGER)
|
||||
-- A SQL has been performed in DYNAMIC EXECUTION mode,
|
||||
-- Then if the DYNAMICALLY EXECUTED SQL statement is a SELECT
|
||||
-- statement, then the cursor is closed.
|
||||
-- Then one can do an other selection on the previous cursor.
|
||||
do
|
||||
end
|
||||
|
||||
exec_immediate (no_descriptor: INTEGER; command: READABLE_STRING_GENERAL)
|
||||
-- In IMMEDIATE EXECUTE mode perform the SQL statement,
|
||||
-- and then check if there is warning message for the execution,
|
||||
do
|
||||
end
|
||||
|
||||
put_col_name (no_descriptor: INTEGER; index: INTEGER; ar: STRING; max_len:INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
put_data (no_descriptor: INTEGER; index: INTEGER; ar: STRING; max_len:INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
put_data_32 (no_descriptor: INTEGER; index: INTEGER; ar: STRING_32; max_len:INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
conv_type (indicator: INTEGER; index: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
--| FIXME
|
||||
--| This description really does not explain a thing...
|
||||
do
|
||||
end
|
||||
|
||||
get_count (no_descriptor: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_data_len (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_col_len (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_col_type (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_integer_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_integer_16_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER_16
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_integer_64_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER_64
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_float_data (no_descriptor: INTEGER; ind: INTEGER): DOUBLE
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_real_data (no_descriptor: INTEGER; ind: INTEGER): REAL
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_boolean_data (no_descriptor: INTEGER; ind: INTEGER): BOOLEAN
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
is_null_data (no_descriptor: INTEGER; ind: INTEGER): BOOLEAN
|
||||
-- Is last retrieved data null?
|
||||
do
|
||||
end
|
||||
|
||||
get_date_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_hour (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_sec (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_min (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_year (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_day (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_month (no_descriptor: INTEGER; ind: INTEGER): INTEGER
|
||||
-- Function used to get data from structure SQLDA filled by FETCH clause.
|
||||
do
|
||||
end
|
||||
|
||||
get_decimal (no_descriptor: INTEGER; ind: INTEGER): detachable TUPLE [digits: STRING_8; sign, precision, scale: INTEGER]
|
||||
-- Function used to get decimal info
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
database_make (i: INTEGER)
|
||||
-- Initialize database c-module
|
||||
do
|
||||
end
|
||||
|
||||
connect (user_name, user_passwd, data_source, application, hostname, role_id: STRING; role_passwd: detachable STRING; group_id: STRING)
|
||||
-- Connect to database
|
||||
do
|
||||
end
|
||||
|
||||
connect_by_connection_string (a_connect_string: STRING)
|
||||
-- Connect to database by connection string
|
||||
do
|
||||
end
|
||||
|
||||
disconnect
|
||||
-- Disconnect the current connection with an database
|
||||
do
|
||||
end
|
||||
|
||||
commit
|
||||
-- Commit the current transaction
|
||||
do
|
||||
end
|
||||
|
||||
rollback
|
||||
-- Commit the current transaction
|
||||
do
|
||||
end
|
||||
|
||||
trancount: INTEGER
|
||||
-- Return the number of transactions now active
|
||||
do
|
||||
end
|
||||
|
||||
begin
|
||||
-- Begin a data base transaction
|
||||
do
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,128 @@
|
||||
note
|
||||
description: "Abstract Database Query"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_QUERY
|
||||
|
||||
inherit
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
create
|
||||
data_reader
|
||||
|
||||
feature {NONE} -- Intialization
|
||||
|
||||
data_reader (a_query: STRING; a_parameters: STRING_TABLE [detachable ANY])
|
||||
-- SQL data reader for the query `a_query' with arguments `a_parameters'
|
||||
do
|
||||
log.write_information (generator + ".data_reader" + " execute query: " + a_query)
|
||||
log.write_debug (generator + ".data_reader" + " arguments:" + log_parameters (a_parameters))
|
||||
query := a_query
|
||||
parameters := a_parameters
|
||||
ensure
|
||||
query_set: query = a_query
|
||||
parameters_set: parameters = a_parameters
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_reader (a_base_selection: DB_SELECTION): detachable LIST [DB_RESULT]
|
||||
-- Execute the Current sql query.
|
||||
do
|
||||
to_implement ("Check test dynamic sequel. to redesign.")
|
||||
create {ARRAYED_LIST [DB_RESULT]} Result.make (100)
|
||||
a_base_selection.set_container (Result)
|
||||
set_map_name (a_base_selection)
|
||||
a_base_selection.set_query (query)
|
||||
a_base_selection.execute_query
|
||||
if a_base_selection.is_ok then
|
||||
a_base_selection.load_result
|
||||
Result := a_base_selection.container
|
||||
else
|
||||
log.write_error (generator + "." + a_base_selection.error_message_32)
|
||||
end
|
||||
unset_map_name (a_base_selection)
|
||||
a_base_selection.terminate
|
||||
end
|
||||
|
||||
execute_change (a_base_change: DB_CHANGE)
|
||||
-- Execute the Current sql query to change/update data in the database.
|
||||
do
|
||||
to_implement ("Check test dynamic sequel. to redesign.")
|
||||
set_map_name (a_base_change)
|
||||
a_base_change.set_query (query)
|
||||
a_base_change.execute_query
|
||||
unset_map_name (a_base_change)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
query: STRING
|
||||
-- SQL query to execute.
|
||||
|
||||
parameters: STRING_TABLE [detachable ANY]
|
||||
-- query parameters.
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
set_map_name (a_base_selection: DB_EXPRESSION)
|
||||
-- Store parameters `item' and their `key'.
|
||||
do
|
||||
from
|
||||
parameters.start
|
||||
until
|
||||
parameters.after
|
||||
loop
|
||||
a_base_selection.set_map_name (parameters.item_for_iteration, parameters.key_for_iteration)
|
||||
parameters.forth
|
||||
end
|
||||
end
|
||||
|
||||
unset_map_name (a_base_selection: DB_EXPRESSION)
|
||||
-- Remove parameters item associated with key `key'.
|
||||
do
|
||||
from
|
||||
parameters.start
|
||||
until
|
||||
parameters.after
|
||||
loop
|
||||
a_base_selection.unset_map_name (parameters.key_for_iteration)
|
||||
parameters.forth
|
||||
end
|
||||
end
|
||||
|
||||
log_parameters (a_parameters: like parameters): STRING
|
||||
-- Parameters to log with name and value
|
||||
-- exclude sensitive information.
|
||||
do
|
||||
create Result.make_empty
|
||||
from
|
||||
a_parameters.start
|
||||
until
|
||||
a_parameters.after
|
||||
loop
|
||||
Result.append ("name:")
|
||||
Result.append (a_parameters.key_for_iteration.as_string_32)
|
||||
Result.append (", value:")
|
||||
if
|
||||
a_parameters.key_for_iteration.has_substring ("Password") or else
|
||||
a_parameters.key_for_iteration.has_substring ("password")
|
||||
then
|
||||
-- Data to exclude
|
||||
else
|
||||
if attached a_parameters.item_for_iteration as l_item then
|
||||
Result.append (l_item.out)
|
||||
end
|
||||
end
|
||||
Result.append ("%N")
|
||||
a_parameters.forth
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end -- DATABASE_QUERY
|
||||
@@ -0,0 +1,33 @@
|
||||
note
|
||||
description: "Help to encode sql queries, to prevent sql injections."
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
EIS: "SQL server injection", "src=http://blogs.msdn.com/b/raulga/archive/2007/01/04/dynamic-sql-sql-injection.aspx", "protocol=url"
|
||||
expanded class
|
||||
DATABASE_SQL_SERVER_ENCODER
|
||||
|
||||
inherit
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
feature -- Escape SQL input
|
||||
|
||||
encode (a_string:READABLE_STRING_32): READABLE_STRING_32
|
||||
-- Escape single quote (') and braces ([,]).
|
||||
local
|
||||
l_string: STRING
|
||||
do
|
||||
l_string := a_string.twin
|
||||
if not l_string.is_empty then
|
||||
l_string.replace_substring_all ("[", "[[")
|
||||
l_string.replace_substring_all ("]", "]]")
|
||||
if l_string.index_of ('%'', 1) > 0 then
|
||||
l_string.replace_substring ("[", 1, l_string.index_of ('%'', 1))
|
||||
end
|
||||
if l_string.last_index_of ('%'', l_string.count) > 0 then
|
||||
l_string.replace_substring ("]", l_string.last_index_of ('%'', l_string.count), l_string.count)
|
||||
end
|
||||
end
|
||||
Result := l_string
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,193 @@
|
||||
note
|
||||
description: "Database Store Procedure"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_STORE_PROCEDURE
|
||||
|
||||
inherit
|
||||
|
||||
SHARED_ERROR
|
||||
|
||||
create
|
||||
data_reader, data_writer
|
||||
|
||||
feature -- Intialization
|
||||
|
||||
data_reader (a_sp: STRING; a_parameters: HASH_TABLE [ANY, STRING_32])
|
||||
-- SQL data reader for the stored procedure `a_sp' with arguments `a_parameters'.
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
log.write_information (generator + ".data_reader" + " execute store procedure: " + a_sp)
|
||||
log.write_debug (generator + ".data_reader" + " arguments:" + log_parameters (a_parameters))
|
||||
if not l_retried then
|
||||
stored_procedure := a_sp
|
||||
parameters := a_parameters
|
||||
create proc.make (stored_procedure)
|
||||
proc.load
|
||||
if not a_parameters.is_empty then
|
||||
proc.set_arguments_32 (a_parameters.current_keys, a_parameters.linear_representation.to_array)
|
||||
end
|
||||
if proc.exists then
|
||||
if proc.text_32 /= Void then
|
||||
debug
|
||||
log.write_debug ( generator + ".data_reader: " + proc.text_32)
|
||||
end
|
||||
end
|
||||
else
|
||||
has_error := True
|
||||
error_message := proc.error_message_32
|
||||
error_code := proc.error_code
|
||||
log.write_error (generator + ".data_witer message:" + proc.error_message_32 + " code:" + proc.error_code.out)
|
||||
end
|
||||
else
|
||||
stored_procedure := a_sp
|
||||
parameters := a_parameters
|
||||
create proc.make (stored_procedure)
|
||||
end
|
||||
rescue
|
||||
set_last_error_from_exception ("SQL execution")
|
||||
log.write_critical (generator+ ".data_reader " + last_error_message)
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
data_writer (a_sp: STRING; a_parameters: HASH_TABLE [ANY, STRING_32])
|
||||
-- SQL data reader for the stored procedure `a_sp' with arguments `a_parameters'
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
log.write_information (generator + ".data_reader" + " execute store procedure: " + a_sp)
|
||||
log.write_debug (generator + ".data_reader" + " arguments:" + log_parameters (a_parameters))
|
||||
if not l_retried then
|
||||
stored_procedure := a_sp
|
||||
parameters := a_parameters
|
||||
create proc.make (stored_procedure)
|
||||
proc.load
|
||||
proc.set_arguments_32 (a_parameters.current_keys, a_parameters.linear_representation.to_array)
|
||||
if proc.exists then
|
||||
if proc.text_32 /= Void then
|
||||
debug
|
||||
log.write_debug ( generator + ".data_writer: " + proc.text_32)
|
||||
end
|
||||
end
|
||||
else
|
||||
has_error := True
|
||||
error_message := proc.error_message_32
|
||||
error_code := proc.error_code
|
||||
log.write_error (generator + ".data_witer message:" + proc.error_message_32 + " code:" + proc.error_code.out)
|
||||
end
|
||||
else
|
||||
stored_procedure := a_sp
|
||||
parameters := a_parameters
|
||||
create proc.make (stored_procedure)
|
||||
end
|
||||
rescue
|
||||
set_last_error_from_exception ("SQL execution")
|
||||
log.write_critical (generator+ ".data_reader " + last_error_message)
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
|
||||
execute_reader (a_base_selection: DB_SELECTION): detachable LIST [DB_RESULT]
|
||||
-- Execute the Current store procedure.
|
||||
do
|
||||
create {ARRAYED_LIST [DB_RESULT]} Result.make (100)
|
||||
a_base_selection.set_container (Result)
|
||||
set_map_name (a_base_selection)
|
||||
proc.execute (a_base_selection)
|
||||
a_base_selection.load_result
|
||||
Result := a_base_selection.container
|
||||
unset_map_name (a_base_selection)
|
||||
end
|
||||
|
||||
execute_writer (a_base_change: DB_CHANGE)
|
||||
-- Execute the Current store procedure.
|
||||
do
|
||||
set_map_name (a_base_change)
|
||||
proc.execute (a_base_change)
|
||||
unset_map_name (a_base_change)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
proc: DB_PROC
|
||||
-- object to create and execute stored procedure.
|
||||
|
||||
parameters: HASH_TABLE [detachable ANY, STRING_32]
|
||||
-- Parameters to be used by the stored procedure.
|
||||
|
||||
stored_procedure: STRING
|
||||
-- Store procedure to execute
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- Is there an error.
|
||||
|
||||
error_message: detachable STRING_32
|
||||
-- Last error message.
|
||||
|
||||
error_code: INTEGER
|
||||
-- Last error code.
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
set_map_name (a_base_selection: DB_EXPRESSION)
|
||||
-- Store parameters `item' and their `key'.
|
||||
do
|
||||
from
|
||||
parameters.start
|
||||
until
|
||||
parameters.after
|
||||
loop
|
||||
a_base_selection.set_map_name (parameters.item_for_iteration, parameters.key_for_iteration)
|
||||
parameters.forth
|
||||
end
|
||||
end
|
||||
|
||||
unset_map_name (a_base_selection: DB_EXPRESSION)
|
||||
-- Remove parameters item associated with key `key'.
|
||||
do
|
||||
from
|
||||
parameters.start
|
||||
until
|
||||
parameters.after
|
||||
loop
|
||||
a_base_selection.unset_map_name (parameters.key_for_iteration)
|
||||
parameters.forth
|
||||
end
|
||||
end
|
||||
|
||||
log_parameters (a_parameters: like parameters): STRING
|
||||
-- Parameters to log with name and value
|
||||
-- exclude sensitive information.
|
||||
do
|
||||
create Result.make_empty
|
||||
from
|
||||
a_parameters.start
|
||||
until
|
||||
a_parameters.after
|
||||
loop
|
||||
Result.append ("name:")
|
||||
Result.append (a_parameters.key_for_iteration)
|
||||
Result.append (", value:")
|
||||
if
|
||||
a_parameters.key_for_iteration.has_substring ("Password") or else
|
||||
a_parameters.key_for_iteration.has_substring ("password")
|
||||
then
|
||||
-- Data to exclude
|
||||
else
|
||||
if attached a_parameters.item_for_iteration as l_item then
|
||||
Result.append (l_item.out)
|
||||
end
|
||||
end
|
||||
Result.append ("%N")
|
||||
a_parameters.forth
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
note
|
||||
description: "Error from database"
|
||||
date: "$Date: 2013-08-08 16:39:49 -0300 (ju. 08 de ago. de 2013) $"
|
||||
revision: "$Revision: 195 $"
|
||||
|
||||
class
|
||||
DATABASE_ERROR
|
||||
|
||||
inherit
|
||||
ERROR_CUSTOM
|
||||
|
||||
create
|
||||
make_from_message
|
||||
|
||||
feature {NONE} -- Init
|
||||
|
||||
make_from_message (a_m: like message; a_code: like code)
|
||||
-- Create from `a_m'
|
||||
do
|
||||
make (a_code, once "Database Error", a_m)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
note
|
||||
description: "Database error handler"
|
||||
date: "$Date: 2013-08-08 16:39:49 -0300 (ju. 08 de ago. de 2013) $"
|
||||
revision: "$Revision: 195 $"
|
||||
|
||||
class
|
||||
DATABASE_ERROR_HANDLER
|
||||
|
||||
inherit
|
||||
ERROR_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Error operation
|
||||
|
||||
add_database_error (a_message: READABLE_STRING_32; a_code: INTEGER)
|
||||
-- Add a database error.
|
||||
local
|
||||
l_error: DATABASE_ERROR
|
||||
do
|
||||
create l_error.make_from_message (a_message, a_code)
|
||||
add_error (l_error)
|
||||
end
|
||||
|
||||
add_database_no_change_error (a_message: READABLE_STRING_32; a_code: INTEGER)
|
||||
-- Add a database error.
|
||||
local
|
||||
l_error: DATABASE_NO_CHANGE_ERROR
|
||||
do
|
||||
create l_error.make_from_message (a_message, a_code)
|
||||
add_error (l_error)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
note
|
||||
description: "Summary description for {DATABASE_NO_CHANGE_ERROR}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
DATABASE_NO_CHANGE_ERROR
|
||||
|
||||
inherit
|
||||
DATABASE_ERROR
|
||||
redefine
|
||||
make_from_message
|
||||
end
|
||||
|
||||
create
|
||||
make_from_message
|
||||
|
||||
feature {NONE} -- Init
|
||||
|
||||
make_from_message (a_m: like message; a_code: like code)
|
||||
-- Create from `a_m'
|
||||
do
|
||||
make (a_code, once "Database No Change Error", a_m)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
note
|
||||
description: "Helper for paramenter Names"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
deferred class
|
||||
PARAMETER_NAME_HELPER
|
||||
|
||||
feature -- String
|
||||
|
||||
string_parameter (a_value: STRING; a_length: INTEGER): STRING
|
||||
-- Adjust a parameter `a_value' to the lenght `a_length'.
|
||||
require
|
||||
valid_length: a_length > 0
|
||||
do
|
||||
if a_value.count <= a_length then
|
||||
Result := a_value
|
||||
else
|
||||
create Result.make_from_string (a_value.substring (1, a_length))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,153 @@
|
||||
note
|
||||
description: "Provides security routine helpers"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
SECURITY_PROVIDER
|
||||
|
||||
inherit
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
feature -- Access
|
||||
|
||||
token: STRING
|
||||
-- Cryptographic random base 64 string.
|
||||
do
|
||||
Result := salt_with_size (5)
|
||||
-- Remove trailing equal sign
|
||||
Result.keep_head (Result.count - 1)
|
||||
end
|
||||
|
||||
salt: STRING
|
||||
-- Cryptographic random number of 16 bytes.
|
||||
do
|
||||
Result := salt_with_size (16)
|
||||
end
|
||||
|
||||
password: STRING
|
||||
-- Cryptographic random password of 10 bytes.
|
||||
do
|
||||
Result := salt_with_size (10)
|
||||
-- Remove trailing equal signs
|
||||
Result.keep_head (Result.count - 2)
|
||||
end
|
||||
|
||||
password_hash (a_password, a_salt: STRING): STRING
|
||||
-- Password hash based on password `a_password' and salt value `a_salt'.
|
||||
do
|
||||
Result := sha1_string (a_password + a_salt )
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
salt_with_size (a_val: INTEGER): STRING
|
||||
-- Return a salt with size `a_val'.
|
||||
local
|
||||
l_salt: SALT_XOR_SHIFT_64_GENERATOR
|
||||
l_array: ARRAY [INTEGER_8]
|
||||
i: INTEGER
|
||||
do
|
||||
create l_salt.make (a_val)
|
||||
create l_array.make_empty
|
||||
i := 1
|
||||
across
|
||||
l_salt.new_sequence as c
|
||||
loop
|
||||
l_array.force (c.item.as_integer_8, i)
|
||||
i := i + 1
|
||||
end
|
||||
Result := encode_base_64 (l_array)
|
||||
end
|
||||
|
||||
sha1_string (a_str: STRING): STRING
|
||||
-- SHA1 diggest of `a_str'.
|
||||
do
|
||||
sha1.update_from_string (a_str)
|
||||
Result := sha1.digest_as_string
|
||||
sha1.reset
|
||||
end
|
||||
|
||||
sha1: SHA1
|
||||
-- Create a SHA1 object.
|
||||
once
|
||||
create Result.make
|
||||
end
|
||||
|
||||
feature -- Encoding
|
||||
|
||||
|
||||
encode_base_64 (bytes: SPECIAL [INTEGER_8]): STRING_8
|
||||
-- Encodes a byte array into a STRING doing base64 encoding.
|
||||
local
|
||||
l_output: SPECIAL [INTEGER_8]
|
||||
l_remaining: INTEGER
|
||||
i, ptr: INTEGER
|
||||
char: CHARACTER
|
||||
do
|
||||
to_implement ("Check existing code to do that!!!.")
|
||||
create l_output.make_filled (0, ((bytes.count + 2) // 3) * 4)
|
||||
l_remaining := bytes.count
|
||||
from
|
||||
i := 0
|
||||
ptr := 0
|
||||
until
|
||||
l_remaining <= 3
|
||||
loop
|
||||
l_output [ptr] := encode_value (bytes [i] |>> 2)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i] & 0x3) |<< 4) | ((bytes [i + 1] |>> 4) & 0xF))
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i + 1] & 0xF) |<< 2) | ((bytes [i + 2] |>> 6) & 0x3))
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (bytes [i + 2] & 0x3F)
|
||||
ptr := ptr + 1
|
||||
l_remaining := l_remaining - 3
|
||||
i := i + 3
|
||||
end
|
||||
-- encode when exactly 1 element (left) to encode
|
||||
char := '='
|
||||
if l_remaining = 1 then
|
||||
l_output [ptr] := encode_value (bytes [i] |>> 2)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i]) & 0x3) |<< 4)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := char.code.as_integer_8
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := char.code.as_integer_8
|
||||
ptr := ptr + 1
|
||||
end
|
||||
|
||||
-- encode when exactly 2 elements (left) to encode
|
||||
if l_remaining = 2 then
|
||||
l_output [ptr] := encode_value (bytes [i] |>> 2)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i] & 0x3) |<< 4) | ((bytes [i + 1] |>> 4) & 0xF));
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value ((bytes [i + 1] & 0xF) |<< 2);
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := char.code.as_integer_8
|
||||
ptr := ptr + 1
|
||||
end
|
||||
Result := ""
|
||||
across
|
||||
l_output as elem
|
||||
loop
|
||||
Result.append_character (elem.item.to_character_8)
|
||||
end
|
||||
end
|
||||
|
||||
base64_map: SPECIAL [CHARACTER_8]
|
||||
-- Table for Base64 encoding.
|
||||
once
|
||||
Result := ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").area
|
||||
end
|
||||
|
||||
encode_value (i: INTEGER_8): INTEGER_8
|
||||
-- Encode `i'.
|
||||
do
|
||||
Result := base64_map [i & 0x3F].code.as_integer_8
|
||||
end
|
||||
|
||||
end
|
||||
53
library/persistence/implementation/common/string_helper.e
Normal file
53
library/persistence/implementation/common/string_helper.e
Normal file
@@ -0,0 +1,53 @@
|
||||
note
|
||||
description: "Summary description for {STRING_HELPER}."
|
||||
date: "$Date: 2014-08-08 16:02:11 -0300 (vi., 08 ago. 2014) $"
|
||||
revision: "$Revision: 95593 $"
|
||||
|
||||
class
|
||||
STRING_HELPER
|
||||
|
||||
feature -- Access
|
||||
|
||||
is_blank (s: detachable READABLE_STRING_32): BOOLEAN
|
||||
local
|
||||
i,n: INTEGER
|
||||
do
|
||||
Result := True
|
||||
if s /= Void then
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n or not Result
|
||||
loop
|
||||
Result := s[i].is_space
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
indented_text (pre: READABLE_STRING_8; t: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Indendted text.
|
||||
local
|
||||
s8: STRING_8
|
||||
do
|
||||
s8 := t.string
|
||||
s8.prepend (pre)
|
||||
s8.replace_substring_all ("%N", "%N" + pre)
|
||||
Result := s8
|
||||
end
|
||||
|
||||
|
||||
json_encode (a_string: STRING): STRING
|
||||
-- json encode `a_string'.
|
||||
local
|
||||
encode: SHARED_JSON_ENCODER
|
||||
do
|
||||
create encode
|
||||
Result := encode.json_encoder.encoded_string (a_string)
|
||||
debug
|
||||
print ("%NResult" + Result)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="persistence_mysql" uuid="DC757CBD-D8C4-44D6-A07F-C1148D8D233E" library_target="persistence_mysql">
|
||||
<target name="persistence_mysql">
|
||||
<root all_classes="true"/>
|
||||
<option warning="true" void_safety="all">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="console_application" value="true"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
|
||||
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||
|
||||
<library name="layout" location="..\..\..\layout\layout-safe.ecf"/>
|
||||
<library name="model" location="..\..\..\model\cms_model-safe.ecf"/>
|
||||
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging-safe.ecf"/>
|
||||
<library name="mysql" location="$ISE_LIBRARY\library\store\dbms\rdbms\mysql\mysql-safe.ecf"/>
|
||||
<library name="store" location="$ISE_LIBRARY\library\store\store-safe.ecf" readonly="false"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<cluster name="persistence_mysql" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
<cluster name="interface" location="..\..\interface\" recursive="true"/>
|
||||
<cluster name="common" location="..\common\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/database/database_connection_odbc.e</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1 @@
|
||||
Added Stored Procedures
|
||||
@@ -0,0 +1,163 @@
|
||||
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
|
||||
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
|
||||
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Schema mydb
|
||||
-- -----------------------------------------------------
|
||||
-- -----------------------------------------------------
|
||||
-- Schema cms_dev
|
||||
-- -----------------------------------------------------
|
||||
CREATE SCHEMA IF NOT EXISTS `cms_dev` DEFAULT CHARACTER SET latin1 ;
|
||||
USE `cms_dev` ;
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms_dev`.`users`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`users` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`username` VARCHAR(100) NOT NULL,
|
||||
`password` VARCHAR(100) NOT NULL,
|
||||
`salt` VARCHAR(100) NOT NULL,
|
||||
`email` VARCHAR(250) NOT NULL,
|
||||
`creation_date` DATETIME NULL DEFAULT NULL,
|
||||
`last_login_date` DATETIME NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `username` (`username` ASC))
|
||||
ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 2
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms_dev`.`nodes`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`nodes` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`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,
|
||||
`author_id` INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
`version` INT(10) UNSIGNED ZEROFILL NULL DEFAULT NULL,
|
||||
`editor_id` INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `fk_nodes_users1_idx` (`author_id` ASC),
|
||||
INDEX `fk_nodes_users2_idx` (`editor_id` ASC),
|
||||
CONSTRAINT `fk_nodes_users1`
|
||||
FOREIGN KEY (`author_id`)
|
||||
REFERENCES `cms_dev`.`users` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
CONSTRAINT `fk_nodes_users2`
|
||||
FOREIGN KEY (`editor_id`)
|
||||
REFERENCES `cms_dev`.`users` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 11
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms_dev`.`roles`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`roles` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`role` VARCHAR(100) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `role` (`role` ASC))
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms_dev`.`permissions`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`permissions` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(45) NOT NULL,
|
||||
`roles_id` INT(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `name_UNIQUE` (`name` ASC),
|
||||
INDEX `fk_permissions_roles1_idx` (`roles_id` ASC),
|
||||
CONSTRAINT `fk_permissions_roles1`
|
||||
FOREIGN KEY (`roles_id`)
|
||||
REFERENCES `cms_dev`.`roles` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms_dev`.`profiles`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`profiles` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`key` VARCHAR(45) NOT NULL,
|
||||
`value` VARCHAR(100) NULL DEFAULT NULL,
|
||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `key_UNIQUE` (`key` ASC),
|
||||
INDEX `fk_profiles_users1_idx` (`users_id` ASC),
|
||||
CONSTRAINT `fk_profiles_users1`
|
||||
FOREIGN KEY (`users_id`)
|
||||
REFERENCES `cms_dev`.`users` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms_dev`.`users_nodes`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`users_nodes` (
|
||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
||||
`nodes_id` INT(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`users_id`, `nodes_id`),
|
||||
INDEX `fk_users_has_nodes_nodes1_idx` (`nodes_id` ASC),
|
||||
INDEX `fk_users_has_nodes_users_idx` (`users_id` ASC),
|
||||
CONSTRAINT `fk_users_has_nodes_nodes1`
|
||||
FOREIGN KEY (`nodes_id`)
|
||||
REFERENCES `cms_dev`.`nodes` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
CONSTRAINT `fk_users_has_nodes_users`
|
||||
FOREIGN KEY (`users_id`)
|
||||
REFERENCES `cms_dev`.`users` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms_dev`.`users_roles`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`users_roles` (
|
||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
||||
`roles_id` INT(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`users_id`, `roles_id`),
|
||||
INDEX `fk_users_has_roles_roles1_idx` (`roles_id` ASC),
|
||||
INDEX `fk_users_has_roles_users1_idx` (`users_id` ASC),
|
||||
CONSTRAINT `fk_users_has_roles_roles1`
|
||||
FOREIGN KEY (`roles_id`)
|
||||
REFERENCES `cms_dev`.`roles` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
CONSTRAINT `fk_users_has_roles_users1`
|
||||
FOREIGN KEY (`users_id`)
|
||||
REFERENCES `cms_dev`.`users` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
SET SQL_MODE=@OLD_SQL_MODE;
|
||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
||||
14
library/persistence/implementation/mysql/scripts/tables.sql
Normal file
14
library/persistence/implementation/mysql/scripts/tables.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
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)
|
||||
);
|
||||
@@ -0,0 +1,8 @@
|
||||
DELIMITER $$
|
||||
CREATE TRIGGER update_editor
|
||||
AFTER INSERT ON `users_nodes` FOR EACH ROW
|
||||
UPDATE Nodes
|
||||
SET editor_id = NEW.users_id
|
||||
WHERE id = NEW.nodes_id;
|
||||
$$
|
||||
DELIMITER ;
|
||||
270
library/persistence/implementation/mysql/src/cms_storage_mysql.e
Normal file
270
library/persistence/implementation/mysql/src/cms_storage_mysql.e
Normal file
@@ -0,0 +1,270 @@
|
||||
note
|
||||
description: "Summary description for {CMS_STORAGE_MYSQL}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_STORAGE_MYSQL
|
||||
|
||||
inherit
|
||||
|
||||
CMS_STORAGE
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
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 )
|
||||
create node_provider.make (a_connection)
|
||||
create user_provider.make (a_connection)
|
||||
create error_handler.make
|
||||
end
|
||||
|
||||
|
||||
feature -- Access: user
|
||||
|
||||
has_user: BOOLEAN
|
||||
-- Has any user?
|
||||
do
|
||||
Result := user_provider.has_user
|
||||
end
|
||||
|
||||
all_users: LIST [CMS_USER]
|
||||
do
|
||||
to_implement (generator + ".all_users")
|
||||
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
|
||||
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
|
||||
to_implement (generator + ".user_collaborator_nodes")
|
||||
create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
|
||||
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
|
||||
to_implement (generator + ".user_author_nodes")
|
||||
create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
|
||||
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 -- 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
|
||||
connection.begin_transaction
|
||||
user_provider.new_user (a_user.name, l_password, l_email)
|
||||
connection.commit
|
||||
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: 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
|
||||
-- <Precursor>
|
||||
do
|
||||
Result := node_provider.node (a_id)
|
||||
|
||||
end
|
||||
|
||||
node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
|
||||
-- <Precursor>
|
||||
do
|
||||
Result := node_provider.node_author (a_id)
|
||||
|
||||
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)
|
||||
across node_provider.node_collaborators (a_id) as c loop Result.force (c.item) end
|
||||
end
|
||||
|
||||
feature -- Node
|
||||
|
||||
save_node (a_node: CMS_NODE)
|
||||
-- <Precursor>
|
||||
do
|
||||
node_provider.new_node (a_node)
|
||||
|
||||
end
|
||||
|
||||
delete_node (a_id: INTEGER_64)
|
||||
do
|
||||
node_provider.delete_from_user_nodes(a_id)
|
||||
node_provider.delete_node (a_id)
|
||||
|
||||
end
|
||||
|
||||
update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE)
|
||||
-- <Precursor>
|
||||
do
|
||||
node_provider.update_node (a_id, a_node)
|
||||
|
||||
end
|
||||
|
||||
update_node_title (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- <Precursor>
|
||||
do
|
||||
node_provider.update_node_title (a_node_id, a_title)
|
||||
internal_node_update (a_id, a_node_id)
|
||||
|
||||
end
|
||||
|
||||
update_node_summary (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
|
||||
-- <Precursor>
|
||||
do
|
||||
node_provider.update_node_summary (a_node_id, a_summary)
|
||||
internal_node_update (a_id, a_node_id)
|
||||
|
||||
end
|
||||
|
||||
update_node_content (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
|
||||
-- <Precursor>
|
||||
do
|
||||
node_provider.update_node_content (a_node_id, a_content)
|
||||
internal_node_update (a_id, a_node_id)
|
||||
|
||||
end
|
||||
|
||||
feature {NONE} -- NODE Implemenation
|
||||
|
||||
internal_node_update (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id)
|
||||
-- Update node editor or add collaborator.
|
||||
do
|
||||
if not node_provider.is_collaborator (a_id, a_node_id) then
|
||||
node_provider.add_collaborator (a_id, a_node_id)
|
||||
else
|
||||
node_provider.update_node_last_editor (a_id, a_node_id)
|
||||
end
|
||||
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} -- Post process
|
||||
|
||||
|
||||
node_provider: NODE_DATA_PROVIDER
|
||||
-- Node Data provider.
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- User Data provider.
|
||||
|
||||
connection: DATABASE_CONNECTION
|
||||
-- Current database connection.
|
||||
end
|
||||
@@ -0,0 +1,140 @@
|
||||
note
|
||||
description: "Object that handle a database connection for ODBC"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_CONNECTION_MYSQL
|
||||
|
||||
inherit
|
||||
|
||||
DATABASE_CONNECTION
|
||||
redefine
|
||||
db_application
|
||||
end
|
||||
|
||||
create
|
||||
make, make_common, make_basic, login_with_connection_string, login_with_schema
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make_common
|
||||
-- Create a database handler for MYSQL with common settings.
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
create database_error_handler.make
|
||||
create db_application.login (username, password)
|
||||
|
||||
if not l_retried then
|
||||
db_application.set_hostname (hostname)
|
||||
db_application.set_data_source (database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
else
|
||||
create db_control.make
|
||||
end
|
||||
rescue
|
||||
create database_error_handler.make
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
make_basic (a_database_name: STRING)
|
||||
-- Create a database handler and
|
||||
-- set database_name to `a_database_name'.
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
create database_error_handler.make
|
||||
create db_application.login (username, password)
|
||||
|
||||
if not l_retried then
|
||||
db_application.set_hostname (hostname)
|
||||
db_application.set_data_source (a_database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
else
|
||||
create db_control.make
|
||||
end
|
||||
rescue
|
||||
create database_error_handler.make
|
||||
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
|
||||
|
||||
-- Create a database handler for ODBC and set `username' to `a_username',
|
||||
-- `password' to `a_password'
|
||||
-- `database_name' to `a_database_name'
|
||||
-- `connection' to `a_connection'
|
||||
do
|
||||
create database_error_handler.make
|
||||
create db_application.login (a_username, a_password)
|
||||
db_application.set_hostname (a_hostname)
|
||||
db_application.set_data_source (a_database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
end
|
||||
|
||||
login_with_connection_string (a_string: STRING)
|
||||
-- Login with `a_connection_string'and immediately connect to database.
|
||||
local
|
||||
l_string: LIST[STRING]
|
||||
l_server: STRING
|
||||
l_port: STRING
|
||||
l_schema: STRING
|
||||
l_user: STRING
|
||||
l_password: STRING
|
||||
do
|
||||
create database_error_handler.make
|
||||
|
||||
l_string := a_string.split (';')
|
||||
l_server := l_string.at (2).split ('=').at (2)
|
||||
l_port := l_string.at (3).split ('=').at (2)
|
||||
l_schema := l_string.at (4).split ('=').at (2)
|
||||
l_user := l_string.at (5).split ('=').at (2)
|
||||
l_password := l_string.at (6).split ('=').at (2)
|
||||
|
||||
create db_application
|
||||
db_application.set_application (l_schema)
|
||||
db_application.set_hostname (l_server + ":" + l_port)
|
||||
db_application.login_and_connect (l_user, l_password)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
end
|
||||
|
||||
login_with_schema (a_schema: STRING; a_username: STRING; a_password: STRING)
|
||||
-- Login with `a_connection_string'and immediately connect to database.
|
||||
do
|
||||
create database_error_handler.make
|
||||
create db_application
|
||||
db_application.set_application (a_schema)
|
||||
db_application.login_and_connect (a_username, a_password)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
end
|
||||
|
||||
feature -- Databse Connection
|
||||
|
||||
db_application: DATABASE_APPL [MYSQL]
|
||||
-- Database application.
|
||||
|
||||
end
|
||||
@@ -0,0 +1,511 @@
|
||||
note
|
||||
description: "Database access for node uses cases."
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
NODE_DATA_PROVIDER
|
||||
|
||||
inherit
|
||||
|
||||
PARAMETER_NAME_HELPER
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (a_connection: DATABASE_CONNECTION)
|
||||
-- Create a data provider.
|
||||
do
|
||||
create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
|
||||
create error_handler.make
|
||||
post_execution
|
||||
end
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Db handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_successful: BOOLEAN
|
||||
-- Is the last execution sucessful?
|
||||
do
|
||||
Result := not error_handler.has_error
|
||||
end
|
||||
|
||||
feature -- Error Handler
|
||||
|
||||
error_handler: ERROR_HANDLER
|
||||
|
||||
feature -- Access
|
||||
|
||||
nodes: DATABASE_ITERATION_CURSOR [CMS_NODE]
|
||||
-- List of nodes.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
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)
|
||||
post_execution
|
||||
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
|
||||
error_handler.reset
|
||||
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)
|
||||
post_execution
|
||||
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
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
end
|
||||
|
||||
count: INTEGER
|
||||
-- Number of items nodes.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
end
|
||||
|
||||
|
||||
last_inserted_node_id: INTEGER
|
||||
-- Last insert node id.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".last_inserted_node_id")
|
||||
create l_parameters.make (0)
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Sql_last_insert_node_id, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := db_handler.read_integer_32 (1)
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
new_node (a_node: CMS_NODE)
|
||||
-- Create a new node.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".new_node")
|
||||
create l_parameters.make (7)
|
||||
l_parameters.put (a_node.title, "title")
|
||||
l_parameters.put (a_node.summary, "summary")
|
||||
l_parameters.put (a_node.content, "content")
|
||||
l_parameters.put (a_node.publication_date, "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
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_insert_node, l_parameters))
|
||||
db_handler.execute_change
|
||||
|
||||
a_node.set_id (last_inserted_node_id)
|
||||
post_execution
|
||||
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
|
||||
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")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_title, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
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
|
||||
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")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_summary, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
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
|
||||
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")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_content, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE)
|
||||
-- Update node.
|
||||
local
|
||||
l_parameters: STRING_TABLE [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_id, "editor")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
delete_node (a_id: INTEGER_64;)
|
||||
-- Delete node with id `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
end
|
||||
|
||||
delete_from_user_nodes (a_id: INTEGER_64)
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".delete_from_user_nodes")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_delete_from_user_node, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- Basic Operations: User_Nodes
|
||||
|
||||
add_author (a_user_id: INTEGER_64; a_node_id: INTEGER_64)
|
||||
-- Add author `a_user_id' to node `a_node_id'
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".add_author")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_user_id,"user_id")
|
||||
l_parameters.put (a_node_id,"id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Sql_update_node_author, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
add_collaborator (a_user_id: INTEGER_64; a_node_id: INTEGER_64)
|
||||
-- Add collaborator `a_user_id' to node `a_node_id'
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".add_collaborator")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_user_id,"users_id")
|
||||
l_parameters.put (a_node_id,"nodes_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Sql_insert_users_nodes, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
update_node_last_editor (a_user_id: INTEGER_64; a_node_id: INTEGER_64)
|
||||
-- Update node last editor.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".add_collaborator")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_user_id,"users_id")
|
||||
l_parameters.put (a_node_id,"nodes_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Slq_update_editor, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
|
||||
author_nodes (a_id:INTEGER_64): DATABASE_ITERATION_CURSOR [CMS_NODE]
|
||||
-- List of Nodes for the given user `a_id'. (the user is the author of the node)
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".author_nodes")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "user_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_user_author, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_node)
|
||||
post_execution
|
||||
end
|
||||
|
||||
collaborator_nodes (a_id:INTEGER_64): DATABASE_ITERATION_CURSOR [CMS_NODE]
|
||||
-- List of Nodes for the given user `a_id' as collaborator.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".collaborator_nodes")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "user_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_user_collaborator, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_node)
|
||||
post_execution
|
||||
end
|
||||
|
||||
|
||||
node_author (a_id: INTEGER_64): 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")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_node_author, l_parameters))
|
||||
db_handler.execute_query
|
||||
if not db_handler.after then
|
||||
Result := fetch_user
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
node_collaborators (a_id: INTEGER_64): DATABASE_ITERATION_CURSOR [CMS_USER]
|
||||
-- List of possible node's collaborator.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".node_collaborators")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "node_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_node_collaborators, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_user)
|
||||
post_execution
|
||||
end
|
||||
|
||||
is_collaborator (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id): BOOLEAN
|
||||
-- Is the user `a_user_id' a collaborator of node `a_node_id'
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".node_collaborators")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_user_id, "user_id")
|
||||
l_parameters.put (a_node_id, "node_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_exist_user_node, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := db_handler.read_integer_32 (1) = 1
|
||||
end
|
||||
post_execution
|
||||
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, 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 --
|
||||
|
||||
|
||||
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
|
||||
|
||||
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 {NONE} -- Implementation
|
||||
|
||||
post_execution
|
||||
-- Post database execution.
|
||||
do
|
||||
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
|
||||
|
||||
end
|
||||
@@ -0,0 +1,216 @@
|
||||
note
|
||||
description: "Summary description for {ROLE_DATA_PROVIDER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ROLE_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)
|
||||
post_execution
|
||||
end
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Db handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_successful: BOOLEAN
|
||||
-- Is the last execution sucessful?
|
||||
do
|
||||
-- Result := db_handler.successful
|
||||
end
|
||||
|
||||
has_roles: BOOLEAN
|
||||
-- Has any role?
|
||||
do
|
||||
Result := count > 0
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
roles: DATABASE_ITERATION_CURSOR [CMS_USER_ROLE]
|
||||
-- List of roles.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".roles")
|
||||
create l_parameters.make (0)
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_roles, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_role)
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- Basic Operations
|
||||
|
||||
new_role (a_role: READABLE_STRING_32)
|
||||
-- Create a new node.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
log.write_information (generator + ".new_role")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_role,"name")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_insert_role, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
role (a_id: INTEGER_64): detachable CMS_USER_ROLE
|
||||
-- Role for the given id `a_id', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".role")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id,"id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_role_by_id, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := fetch_role
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
role_by_name (a_name: READABLE_STRING_32): detachable CMS_USER_ROLE
|
||||
-- Role for the given name `a_name', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".role_by_name")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_name,"name")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_role_by_name, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := fetch_role
|
||||
end
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
end
|
||||
|
||||
save_role_permission (a_role_id: INTEGER; a_permission: READABLE_STRING_32)
|
||||
-- Add permission `a_permission' to the role id `a_role_id'.
|
||||
require
|
||||
valid_id: a_role_id > 0
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
log.write_information (generator + ".save_role_permission")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_permission,"name")
|
||||
l_parameters.put (a_role_id,"id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (SQL_Insert_permissions, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
permission_by_role (a_role_id: INTEGER_64): DATABASE_ITERATION_CURSOR [READABLE_STRING_32]
|
||||
-- List of permission by role `a_role_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".permission_by_role")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_role_id, "id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_permissions, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_permission)
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- New Object
|
||||
|
||||
fetch_role: CMS_USER_ROLE
|
||||
do
|
||||
create Result.make_with_id (0,"")
|
||||
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
|
||||
end
|
||||
|
||||
fetch_permission: STRING_32
|
||||
do
|
||||
create Result.make_empty
|
||||
if attached db_handler.read_string (1) as l_u then
|
||||
Result := l_u
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Sql Queries: Roles
|
||||
|
||||
Select_count: STRING = "select count(*) from Roles;"
|
||||
-- Number of roles.
|
||||
|
||||
Select_roles: STRING = "select * from Roles;"
|
||||
-- roles.
|
||||
|
||||
Select_role_by_id: STRING = "select * from Roles where id =:id;"
|
||||
-- Retrieve role by id if exists.
|
||||
|
||||
Select_role_by_name: STRING = "select * from Roles where role =:name;"
|
||||
-- Retrieve user by name if exists.
|
||||
|
||||
SQL_Insert_role: STRING = "insert into roles (role) values (:name);"
|
||||
-- SQL Insert to add a new node.
|
||||
|
||||
|
||||
feature {NONE} -- Sql Queries: Permissions
|
||||
|
||||
Select_permissions_count: STRING = "select count(*) from permissions where roles_id=:id;"
|
||||
-- Number of permissions for a given role.
|
||||
|
||||
Select_permissions: STRING = "select * from permissions where roles_id=:id;"
|
||||
-- List of permissions for a given role.
|
||||
|
||||
Select_permissions_by_id: STRING = "select name from permissions where roles_id=:id and id=:permissionid;"
|
||||
-- Permission for a given role and permission id
|
||||
|
||||
SQL_Insert_permissions: STRING = "insert into permissions (name, roles_id) values (:name, :id);"
|
||||
-- SQL Insert to add a new node.
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
post_execution
|
||||
-- Post database execution.
|
||||
do
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,337 @@
|
||||
note
|
||||
description: "Summary description for {USER_DATA_PROVIDER}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
USER_DATA_PROVIDER
|
||||
|
||||
inherit
|
||||
|
||||
PARAMETER_NAME_HELPER
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (a_connection: DATABASE_CONNECTION)
|
||||
-- Create a data provider.
|
||||
do
|
||||
create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
|
||||
create error_handler.make
|
||||
post_execution
|
||||
end
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Db handler.
|
||||
|
||||
feature -- Error Handler
|
||||
|
||||
error_handler: ERROR_HANDLER
|
||||
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_successful: BOOLEAN
|
||||
-- Is the last execution sucessful?
|
||||
do
|
||||
Result := not error_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
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
end
|
||||
|
||||
count: INTEGER
|
||||
-- Number of items users.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
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
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- Basic operations: User Roles
|
||||
|
||||
add_role (a_user_id: INTEGER; a_role_id: INTEGER)
|
||||
-- Add Role `a_role_id' to user `a_user_id'
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".add_role")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_user_id,"users_id")
|
||||
l_parameters.put (a_role_id,"roles_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (slq_insert_users_roles, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
user_roles (a_id:INTEGER_64): DATABASE_ITERATION_CURSOR [INTEGER]
|
||||
-- List of Roles id for the given user `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".user_roles")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "user_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_user_roles, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_role_id)
|
||||
post_execution
|
||||
end
|
||||
|
||||
|
||||
feature -- Basic operations: User Profiles
|
||||
|
||||
save_profile_item (a_user_id: INTEGER_64; a_key: READABLE_STRING_32; a_value: READABLE_STRING_32)
|
||||
-- Save a profile item with (a_key and a_value) to the given user `user_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".save_profile_item")
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_key, "key")
|
||||
l_parameters.put (a_value, "value")
|
||||
l_parameters.put (a_user_id, "users_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_instert_profile_item, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
save_profile (a_user_id: INTEGER_64; a_user_profile: CMS_USER_PROFILE)
|
||||
-- Save a profile item with (a_key and a_value) to the given user `user_id'.
|
||||
local
|
||||
l_cursor: TABLE_ITERATION_CURSOR [READABLE_STRING_8, READABLE_STRING_GENERAL]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".save_profile")
|
||||
from
|
||||
l_cursor := a_user_profile.new_cursor
|
||||
until
|
||||
l_cursor.after
|
||||
loop
|
||||
save_profile_item (a_user_id, l_cursor.key.as_string_32, l_cursor.item)
|
||||
l_cursor.forth
|
||||
end
|
||||
|
||||
post_execution
|
||||
end
|
||||
|
||||
user_profile (a_user_id: INTEGER_64): CMS_USER_PROFILE
|
||||
-- User profile for a user with id `a_user_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
log.write_information (generator + ".user_profile")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_user_id, "users_id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_user_profile, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make
|
||||
if not db_handler.after then
|
||||
from
|
||||
db_handler.start
|
||||
until
|
||||
db_handler.after
|
||||
loop
|
||||
if
|
||||
attached db_handler.read_string (1) as l_key and then
|
||||
attached db_handler.read_string (2) as l_value
|
||||
then
|
||||
Result.force (l_value, l_key)
|
||||
end
|
||||
db_handler.forth
|
||||
end
|
||||
end
|
||||
post_execution
|
||||
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
|
||||
|
||||
fetch_role_id: INTEGER
|
||||
do
|
||||
if attached db_handler.read_integer_32 (1) as l_id then
|
||||
Result := l_id
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Sql Queries: USER
|
||||
|
||||
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.
|
||||
|
||||
|
||||
feature {NONE} -- Sql Queries: USER_ROLES
|
||||
|
||||
Slq_insert_users_roles: STRING = "insert into users_roles (users_id, roles_id) values (:users_id, :roles_id);"
|
||||
|
||||
Select_user_roles: STRING = "Select roles_id from users_roles where users_id = :user_id"
|
||||
|
||||
feature {NONE} -- SQL Queries: Profile
|
||||
|
||||
Select_instert_profile_item: STRING = "insert into profiles (profiles.key, value, users_id) values (:key, :value, :users_id);"
|
||||
|
||||
Select_user_profile: STRING = "Select profiles.key, value from profiles where users_id = :users_id;"
|
||||
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
post_execution
|
||||
-- Post database execution.
|
||||
do
|
||||
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
|
||||
|
||||
end
|
||||
125
library/persistence/implementation/mysql/tests/application.e
Normal file
125
library/persistence/implementation/mysql/tests/application.e
Normal file
@@ -0,0 +1,125 @@
|
||||
note
|
||||
description : "tests application root class"
|
||||
date : "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision : "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
ARGUMENTS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
local
|
||||
user: USER_DATA_PROVIDER
|
||||
node: NODE_DATA_PROVIDER
|
||||
l_security: SECURITY_PROVIDER
|
||||
l_profile, l_db_profile: CMS_USER_PROFILE
|
||||
l_cursor: TABLE_ITERATION_CURSOR [READABLE_STRING_8, READABLE_STRING_8]
|
||||
l_list: LIST[CMS_NODE]
|
||||
storage: CMS_STORAGE
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
create connection.login_with_schema ("cms_dev", "root", "")
|
||||
-- create user.make (connection)
|
||||
-- create node.make (connection)
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
|
||||
create {CMS_STORAGE_MYSQL} storage.make (connection)
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
storage.save_user (custom_user ("u2", "p2", "e2"))
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
storage.update_node_title (2,ll_node.id, "New Title")
|
||||
check
|
||||
attached {CMS_NODE} storage.node (1) as u_node and then not (u_node.title ~ ll_node.title) and then u_node.content ~ ll_node.content and then u_node.summary ~ ll_node.summary
|
||||
end
|
||||
end
|
||||
|
||||
-- user.new_user ("test", "test","test@admin.com")
|
||||
-- if attached {CMS_USER} user.user_by_name ("test") as l_user then
|
||||
-- create l_profile.make
|
||||
-- l_profile.force ("Eiffel", "language")
|
||||
-- l_profile.force ("Argentina", "country")
|
||||
-- l_profile.force ("GMT-3", "time zone")
|
||||
-- user.save_profile (l_user.id, l_profile)
|
||||
-- l_db_profile := user.user_profile (l_user.id)
|
||||
-- from
|
||||
-- l_cursor := l_db_profile.new_cursor
|
||||
-- until
|
||||
-- l_cursor.after
|
||||
-- loop
|
||||
-- print (l_cursor.item + " - " + l_cursor.key + "%N")
|
||||
-- l_cursor.forth
|
||||
-- end
|
||||
|
||||
-- create {ARRAYED_LIST[CMS_NODE]} l_list.make (0)
|
||||
-- node.new_node (default_node)
|
||||
-- node.new_node (custom_node ("content1", "summary1", "title1"))
|
||||
-- node.new_node (custom_node ("content2", "summary2", "title2"))
|
||||
-- node.new_node (custom_node ("content3", "summary3", "title3"))
|
||||
-- user.new_user ("u1", "u1", "email")
|
||||
-- if attached user.user_by_name ("u1") as ll_user then
|
||||
-- node.add_collaborator (ll_user.id, 1)
|
||||
-- node.add_collaborator (ll_user.id, 2)
|
||||
-- node.add_collaborator (ll_user.id, 3)
|
||||
-- node.add_collaborator (ll_user.id, 4)
|
||||
|
||||
-- across node.collaborator_nodes (l_user.id) as c loop
|
||||
-- print (c.item.title)
|
||||
-- end
|
||||
|
||||
-- end
|
||||
|
||||
|
||||
-- if attached user.user_by_name ("u1") as ll_user then
|
||||
-- node.add_author (ll_user.id, 1)
|
||||
-- if attached node.node_author (1) as l_author then
|
||||
-- print (l_author.name)
|
||||
-- end
|
||||
-- end
|
||||
|
||||
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Fixture Factory: Users
|
||||
|
||||
default_user: CMS_USER
|
||||
do
|
||||
Result := custom_user ("test", "password", "test@test.com")
|
||||
end
|
||||
|
||||
custom_user (a_name, a_password, a_email: READABLE_STRING_32): CMS_USER
|
||||
do
|
||||
create Result.make (a_name)
|
||||
Result.set_password (a_password)
|
||||
Result.set_email (a_email)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
|
||||
connection: DATABASE_CONNECTION_MYSQL
|
||||
|
||||
|
||||
default_node: CMS_NODE
|
||||
do
|
||||
Result := custom_node ("Default content", "default summary", "Default")
|
||||
end
|
||||
|
||||
custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE
|
||||
do
|
||||
create Result.make (a_content, a_summary, a_title)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,81 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
DATABASE_HANDLER_TEST
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_wrong_database_query
|
||||
-- New test routine
|
||||
local
|
||||
l_parameters: STRING_TABLE[detachable ANY]
|
||||
do
|
||||
create l_parameters.make (0)
|
||||
handler.set_query (create {DATABASE_QUERY}.data_reader ("Sellect from users", l_parameters))
|
||||
handler.execute_query
|
||||
assert ("Has error:", handler.has_error)
|
||||
end
|
||||
|
||||
|
||||
|
||||
test_sequences_of_wrong_and_correct_queries
|
||||
-- New test routine
|
||||
local
|
||||
l_parameters: STRING_TABLE[detachable ANY]
|
||||
do
|
||||
create l_parameters.make (0)
|
||||
handler.set_query (create {DATABASE_QUERY}.data_reader ("Sellect from users;", l_parameters))
|
||||
handler.execute_query
|
||||
assert ("Has error:", handler.has_error)
|
||||
|
||||
handler.set_query (create {DATABASE_QUERY}.data_reader ("Select * from users;", l_parameters))
|
||||
handler.execute_query
|
||||
assert ("Not Has error:",not handler.has_error)
|
||||
end
|
||||
|
||||
|
||||
feature -- Handler
|
||||
|
||||
handler: DATABASE_HANDLER
|
||||
once
|
||||
create {DATABASE_HANDLER_IMPL} Result.make (connection )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing:"execution/isolated"
|
||||
|
||||
class
|
||||
NODE_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_new_node
|
||||
note
|
||||
testing: "execution/isolated"
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
node_provider.new_node (default_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached node_provider.node (1))
|
||||
-- Not exist node with id 2
|
||||
assert ("Not exist node with id 2", node_provider.node (2) = Void)
|
||||
end
|
||||
|
||||
|
||||
test_update_node
|
||||
note
|
||||
testing: "execution/isolated"
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node (content and summary)
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
l_un.set_content ("<h1>Updating test node udpate </h1>")
|
||||
l_un.set_summary ("updating summary")
|
||||
node_provider.update_node (0,l_un)
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_node.content) and then not (ll_node.summary ~ l_node.summary) and then ll_node.title ~ l_node.title )
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title )
|
||||
end
|
||||
|
||||
-- Update node (content and summary and title)
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
l_un.set_content ("<h1>Updating test node udpate </h1>")
|
||||
l_un.set_summary ("updating summary")
|
||||
l_un.set_title ("Updating Test case")
|
||||
node_provider.update_node (0,l_un)
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_node.content) and then not (ll_node.summary ~ l_node.summary) and then not (ll_node.title ~ l_node.title) )
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title )
|
||||
end
|
||||
end
|
||||
|
||||
test_update_title
|
||||
note
|
||||
testing: "execution/isolated"
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node title
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
node_provider.update_node_title (l_un.id, "New Title")
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then ll_node.summary ~ l_un.summary and then not ( ll_node.title ~ l_un.title) and then ll_node.title ~ "New Title" )
|
||||
end
|
||||
end
|
||||
|
||||
test_update_summary
|
||||
note
|
||||
testing: "execution/isolated"
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node summary
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
node_provider.update_node_summary (l_un.id,"New Summary")
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then not (ll_node.summary ~ l_un.summary) and then ll_node.summary ~ "New Summary" and then ll_node.title ~ l_un.title)
|
||||
end
|
||||
end
|
||||
|
||||
test_update_content
|
||||
note
|
||||
testing: "execution/isolated"
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
connection.begin_transaction
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node content
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
node_provider.update_node_content (l_un.id,"New Content")
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_un.content) and then ll_node.content ~ "New Content" and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title)
|
||||
end
|
||||
connection.commit
|
||||
end
|
||||
|
||||
|
||||
test_delete_node
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Delte node 1
|
||||
|
||||
node_provider.delete_node (1)
|
||||
assert ("Node does not exist", node_provider.node (1) = Void)
|
||||
end
|
||||
|
||||
test_recent_nodes
|
||||
-- Content_10, Summary_10, Title_10
|
||||
-- Content_9, Summary_9, Title_9
|
||||
-- ..
|
||||
-- Content_1, Summary_1, Title_1
|
||||
local
|
||||
i : INTEGER
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
across 1 |..| 10 as c loop
|
||||
node_provider.new_node (custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out))
|
||||
end
|
||||
|
||||
-- Scenario (0,10) rows, recents (10 down to 1)
|
||||
i := 10
|
||||
across node_provider.recent_nodes (0, 10) as c loop
|
||||
assert ("Same id:" + i.out, c.item.id = i)
|
||||
i := i - 1
|
||||
end
|
||||
|
||||
-- Scenario (5, 10) rows, recent nodes (5 down to 1)
|
||||
i := 5
|
||||
across node_provider.recent_nodes (5, 10) as c loop
|
||||
assert ("Same id:" + i.out, c.item.id = i)
|
||||
i := i - 1
|
||||
end
|
||||
|
||||
-- Scenario (9,10) rows, recent node 1
|
||||
i := 1
|
||||
across node_provider.recent_nodes (9, 10) as c loop
|
||||
assert ("Same id:" + i.out, c.item.id = i)
|
||||
i := i - 1
|
||||
end
|
||||
|
||||
-- Scenrario 10..10 empty
|
||||
assert ("Empty", node_provider.recent_nodes (10, 10).after)
|
||||
end
|
||||
|
||||
|
||||
test_new_node_without_user
|
||||
do
|
||||
node_provider.new_node (default_node)
|
||||
user_provider.new_user ("u1", "u1", "email")
|
||||
if attached user_provider.user_by_name ("u1") as l_user then
|
||||
assert ("Empty nodes", node_provider.author_nodes (l_user.id).after)
|
||||
end
|
||||
end
|
||||
|
||||
test_new_node_add_author
|
||||
do
|
||||
node_provider.new_node (default_node)
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1))
|
||||
user_provider.new_user ("u1", "u1", "email")
|
||||
if attached user_provider.user_by_name ("u1") as l_user then
|
||||
node_provider.add_author (l_user.id, 1)
|
||||
assert ("Author not void for node 1", attached node_provider.node_author (1))
|
||||
end
|
||||
end
|
||||
|
||||
test_new_node_add_collaborator
|
||||
do
|
||||
node_provider.new_node (default_node)
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1))
|
||||
user_provider.new_user ("u1", "u1", "email")
|
||||
if attached user_provider.user_by_name ("u1") as l_user then
|
||||
node_provider.add_collaborator (l_user.id, 1)
|
||||
assert ("Not Empty Collaborator for node 1", not node_provider.node_collaborators (1).after)
|
||||
end
|
||||
end
|
||||
|
||||
test_multiple_nodes_add_collaborator
|
||||
local
|
||||
l_list: LIST[CMS_NODE]
|
||||
do
|
||||
create {ARRAYED_LIST[CMS_NODE]} l_list.make (0)
|
||||
node_provider.new_node (default_node)
|
||||
node_provider.new_node (custom_node ("content1", "summary1", "title1"))
|
||||
node_provider.new_node (custom_node ("content2", "summary2", "title2"))
|
||||
node_provider.new_node (custom_node ("content3", "summary3", "title3"))
|
||||
user_provider.new_user ("u1", "u1", "email")
|
||||
if attached user_provider.user_by_name ("u1") as l_user then
|
||||
node_provider.add_collaborator (l_user.id, 1)
|
||||
node_provider.add_collaborator (l_user.id, 2)
|
||||
node_provider.add_collaborator (l_user.id, 3)
|
||||
node_provider.add_collaborator (l_user.id, 4)
|
||||
assert ("Not Empty Collaborator for node 1", not node_provider.node_collaborators (1).after)
|
||||
assert ("Not Empty Collaborator for node 2", not node_provider.node_collaborators (2).after)
|
||||
assert ("Not Empty Collaborator for node 3", not node_provider.node_collaborators (3).after)
|
||||
assert ("Not Empty Collaborator for node 4", not node_provider.node_collaborators (4).after)
|
||||
end
|
||||
end
|
||||
|
||||
test_nodes_collaborator
|
||||
local
|
||||
l_list: LIST[CMS_NODE]
|
||||
do
|
||||
create {ARRAYED_LIST[CMS_NODE]} l_list.make (0)
|
||||
node_provider.new_node (default_node)
|
||||
node_provider.new_node (custom_node ("content1", "summary1", "title1"))
|
||||
node_provider.new_node (custom_node ("content2", "summary2", "title2"))
|
||||
node_provider.new_node (custom_node ("content3", "summary3", "title3"))
|
||||
user_provider.new_user ("u1", "u1", "email")
|
||||
if attached user_provider.user_by_name ("u1") as l_user then
|
||||
node_provider.add_collaborator (l_user.id, 1)
|
||||
node_provider.add_collaborator (l_user.id, 2)
|
||||
node_provider.add_collaborator (l_user.id, 3)
|
||||
node_provider.add_collaborator (l_user.id, 4)
|
||||
across node_provider.collaborator_nodes (l_user.id) as c loop
|
||||
l_list.force (c.item)
|
||||
end
|
||||
|
||||
assert ("User is collaborating in 4 nodes", l_list.count = 4)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
node_provider: NODE_DATA_PROVIDER
|
||||
-- node provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- user provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation Fixture Factories
|
||||
|
||||
default_node: CMS_NODE
|
||||
do
|
||||
Result := custom_node ("Default content", "default summary", "Default")
|
||||
end
|
||||
|
||||
custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE
|
||||
do
|
||||
create Result.make (a_content, a_summary, a_title)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
note
|
||||
description: "Summary description for {ROLE_TEST_SET}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ROLE_TEST_SET
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_roles_empty
|
||||
do
|
||||
assert ("Not elements",role_provider.roles.after)
|
||||
assert ("Count = 0", role_provider.count = 0)
|
||||
end
|
||||
|
||||
test_roles_by_id_not_exist
|
||||
do
|
||||
assert ("Void", role_provider.role (1) = Void)
|
||||
end
|
||||
|
||||
test_roles_by_name_not_exist
|
||||
do
|
||||
assert ("Void", role_provider.role_by_name ("admin") = Void)
|
||||
end
|
||||
|
||||
test_new_role
|
||||
do
|
||||
assert ("Count = 0", role_provider.count = 0)
|
||||
role_provider.new_role ("admin")
|
||||
assert ("Count = 1", role_provider.count = 1)
|
||||
assert ("Expected role", attached role_provider.role (1) as l_role and then l_role.name ~ "admin")
|
||||
assert ("Expected role", attached role_provider.role_by_name ("admin") as l_role and then l_role.id = 1)
|
||||
end
|
||||
|
||||
test_permissions_empty_not_exist_role
|
||||
do
|
||||
assert ("Not elements",role_provider.permission_by_role (1).after)
|
||||
end
|
||||
|
||||
test_permissions_empty_exist_role
|
||||
do
|
||||
assert ("Count = 0", role_provider.count = 0)
|
||||
role_provider.new_role ("admin")
|
||||
assert ("Count = 1", role_provider.count = 1)
|
||||
assert ("Exist role",not role_provider.roles.after)
|
||||
assert ("Not permission by role 1 elements",role_provider.permission_by_role (1).after)
|
||||
end
|
||||
|
||||
test_new_role_with_permissions
|
||||
do
|
||||
assert ("Count = 0", role_provider.count = 0)
|
||||
role_provider.new_role ("admin")
|
||||
role_provider.save_role_permission (1, "Create Page")
|
||||
role_provider.save_role_permission (1, "Edit Page")
|
||||
role_provider.save_role_permission (1, "Delete Page")
|
||||
assert ("Count = 1", role_provider.count = 1)
|
||||
assert ("Exist role",not role_provider.roles.after)
|
||||
assert ("Exist role permissions",not role_provider.permission_by_role (1).after)
|
||||
assert ("Not Exist role permissions, for id 2",role_provider.permission_by_role (2).after)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
role_provider: ROLE_DATA_PROVIDER
|
||||
-- role provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,393 @@
|
||||
note
|
||||
description: "Summary description for {STORAGE_TEST_SET}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
STORAGE_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_has_user
|
||||
do
|
||||
assert ("Not has user", not storage.has_user)
|
||||
end
|
||||
|
||||
test_all_users
|
||||
do
|
||||
assert ("to implement all_users", False)
|
||||
end
|
||||
|
||||
test_user_by_id_not_exist
|
||||
do
|
||||
assert ("User does not exist", storage.user_by_id (1) = Void)
|
||||
end
|
||||
|
||||
test_user_by_name_not_exist
|
||||
do
|
||||
assert ("User does not exist", storage.user_by_name ("test") = Void)
|
||||
end
|
||||
|
||||
test_user_by_email_not_exist
|
||||
do
|
||||
assert ("User does not exist", storage.user_by_name ("test@test.com") = Void)
|
||||
end
|
||||
|
||||
test_user_with_bad_id
|
||||
local
|
||||
l_retry: BOOLEAN
|
||||
l_user: detachable CMS_USER
|
||||
do
|
||||
if not l_retry then
|
||||
l_user := storage.user_by_id (0)
|
||||
assert ("Precondition does not get the wrong value", False)
|
||||
else
|
||||
assert ("Expected precondition violation", True)
|
||||
end
|
||||
rescue
|
||||
l_retry := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_user_with_bad_name_empty
|
||||
local
|
||||
l_retry: BOOLEAN
|
||||
l_user: detachable CMS_USER
|
||||
do
|
||||
if not l_retry then
|
||||
l_user := storage.user_by_name ("")
|
||||
assert ("Precondition does not get the wrong value", False)
|
||||
else
|
||||
assert ("Expected precondition violation", True)
|
||||
end
|
||||
rescue
|
||||
l_retry := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_user_with_bad_email_empty
|
||||
local
|
||||
l_retry: BOOLEAN
|
||||
l_user: detachable CMS_USER
|
||||
do
|
||||
if not l_retry then
|
||||
l_user := storage.user_by_email ("")
|
||||
assert ("Precondition does not get the wrong value", False)
|
||||
else
|
||||
assert ("Expected precondition violation", True)
|
||||
end
|
||||
rescue
|
||||
l_retry := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_save_user
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
end
|
||||
|
||||
test_user_by_id
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
if attached {CMS_USER} storage.user_by_id (1) as l_user then
|
||||
assert ("Exist", True)
|
||||
assert ("User test", l_user.name ~ "test")
|
||||
assert ("User id = 1", l_user.id = 1)
|
||||
else
|
||||
assert ("Wrong Implementation", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_user_by_name
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
if attached {CMS_USER} storage.user_by_name ("test") as l_user then
|
||||
assert ("Exist", True)
|
||||
assert ("User nane: test", l_user.name ~ "test")
|
||||
else
|
||||
assert ("Wrong Implementation", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_user_by_email
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
if attached {CMS_USER} storage.user_by_email ("test@test.com") as l_user then
|
||||
assert ("Exist", True)
|
||||
assert ("User email: test@test.com", l_user.email ~ "test@test.com")
|
||||
else
|
||||
assert ("Wrong Implementation", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_invalid_credential
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user test", attached storage.user_by_name ("test"))
|
||||
assert ("Wrong password", not storage.is_valid_credential ("test", "test"))
|
||||
assert ("Wrong user", not storage.is_valid_credential ("test1", "test"))
|
||||
end
|
||||
|
||||
test_valid_credential
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user test", attached storage.user_by_name ("test"))
|
||||
assert ("Valid password", storage.is_valid_credential ("test", "password"))
|
||||
end
|
||||
|
||||
test_recent_nodes_empty
|
||||
do
|
||||
assert ("No recent nodes", storage.recent_nodes (0, 10).is_empty)
|
||||
end
|
||||
|
||||
test_recent_nodes
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
across 1 |..| 10 as c loop
|
||||
l_node := custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out)
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
end
|
||||
l_nodes := storage.recent_nodes (0, 10)
|
||||
assert ("10 recent nodes", l_nodes.count = 10)
|
||||
assert ("First node id=10", l_nodes.first.id = 10)
|
||||
assert ("Last node id=1", l_nodes.last.id = 1)
|
||||
|
||||
|
||||
l_nodes := storage.recent_nodes (5, 10)
|
||||
assert ("5 recent nodes", l_nodes.count = 5)
|
||||
assert ("First node id=5", l_nodes.first.id = 5)
|
||||
assert ("Last node id=1", l_nodes.last.id = 1)
|
||||
|
||||
l_nodes := storage.recent_nodes (9, 10)
|
||||
assert ("1 recent nodes", l_nodes.count = 1)
|
||||
assert ("First node id=1", l_nodes.first.id = 1)
|
||||
assert ("Last node id=1", l_nodes.last.id = 1)
|
||||
|
||||
l_nodes := storage.recent_nodes (10, 10)
|
||||
assert ("Is empty", l_nodes.is_empty)
|
||||
end
|
||||
|
||||
test_node_does_not_exist
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
across 1 |..| 10 as c loop
|
||||
l_node := custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out)
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
end
|
||||
assert ("Not exist node id: 12", storage.node (12) = Void)
|
||||
end
|
||||
|
||||
test_node
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
across 1 |..| 10 as c loop
|
||||
l_node := custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out)
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
end
|
||||
assert ("Node id: 10", attached storage.node (10) as ll_node and then ll_node.title ~ "Title_10" )
|
||||
end
|
||||
|
||||
test_update_node
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
l_node := ll_node.twin
|
||||
l_node.set_content ("New Content")
|
||||
l_node.set_summary ("New Summary")
|
||||
l_node.set_title("New Title")
|
||||
if attached storage.user_by_email (default_user.email) as l_user then
|
||||
storage.update_node (l_user.id,l_node)
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then not (u_node.title ~ ll_node.title) and then not (u_node.content ~ ll_node.content) and then not (u_node.summary ~ ll_node.summary))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_title
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
storage.save_user (custom_user ("u2", "p2", "e2"))
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
storage.update_node_title (2,ll_node.id, "New Title")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then not (u_node.title ~ ll_node.title) and then u_node.content ~ ll_node.content and then u_node.summary ~ ll_node.summary)
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_summary
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
storage.save_user (custom_user ("u2", "p2", "e2"))
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
storage.update_node_summary (2,ll_node.id, "New Summary")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then u_node.title ~ ll_node.title and then u_node.content ~ ll_node.content and then not (u_node.summary ~ ll_node.summary))
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_content
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
storage.save_user (custom_user ("u2", "p2", "e2"))
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
storage.update_node_content (2,ll_node.id, "New Content")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then u_node.title ~ ll_node.title and then not (u_node.content ~ ll_node.content) and then u_node.summary ~ ll_node.summary)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_update_node_title_by_author
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
storage.update_node_title (1,ll_node.id, "New Title")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then not (u_node.title ~ ll_node.title) and then u_node.content ~ ll_node.content and then u_node.summary ~ ll_node.summary)
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_summary_by_author
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
storage.update_node_summary (1,ll_node.id, "New Summary")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then u_node.title ~ ll_node.title and then u_node.content ~ ll_node.content and then not (u_node.summary ~ ll_node.summary))
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_content_by_author
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
l_node := custom_node ("Content", "Summary", "Title")
|
||||
storage.save_user (default_user)
|
||||
l_node.set_author (storage.user_by_email (default_user.email))
|
||||
storage.save_node (l_node)
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
storage.update_node_content (1,ll_node.id, "New Content")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then u_node.title ~ ll_node.title and then not (u_node.content ~ ll_node.content) and then u_node.summary ~ ll_node.summary)
|
||||
end
|
||||
end
|
||||
|
||||
test_delete_node
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
l_user: like {CMS_NODE}.author
|
||||
do
|
||||
storage.save_user (custom_user ("test_delete", "testu", "email"))
|
||||
l_user := storage.user_by_name ("test_delete")
|
||||
across 1 |..| 10 as c loop
|
||||
l_node := custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out)
|
||||
l_node.set_author (l_user)
|
||||
storage.save_node (l_node)
|
||||
end
|
||||
assert ("Exist node id: 10", attached storage.node (10) as ll_node and then ll_node.title ~ "Title_10" )
|
||||
storage.delete_node (10)
|
||||
assert ("Not exist node id: 10", storage.node (10) = Void)
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
storage: CMS_STORAGE
|
||||
-- Storage
|
||||
once
|
||||
create {CMS_STORAGE_MYSQL}Result.make (connection)
|
||||
end
|
||||
|
||||
feature {NONE} -- Fixture Factory: Users
|
||||
|
||||
default_user: CMS_USER
|
||||
do
|
||||
Result := custom_user ("test", "password", "test@test.com")
|
||||
end
|
||||
|
||||
custom_user (a_name, a_password, a_email: READABLE_STRING_32): CMS_USER
|
||||
do
|
||||
create Result.make (a_name)
|
||||
Result.set_password (a_password)
|
||||
Result.set_email (a_email)
|
||||
end
|
||||
|
||||
feature {NONE} -- Fixture Factories: Nodes
|
||||
|
||||
default_node: CMS_NODE
|
||||
do
|
||||
Result := custom_node ("Default content", "default summary", "Default")
|
||||
end
|
||||
|
||||
custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE
|
||||
do
|
||||
create Result.make (a_content, a_summary, a_title)
|
||||
end
|
||||
|
||||
end
|
||||
23
library/persistence/implementation/mysql/tests/tests.ecf
Normal file
23
library/persistence/implementation/mysql/tests/tests.ecf
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="tests">
|
||||
<target name="tests">
|
||||
<root class="APPLICATION" feature="make"/>
|
||||
<option warning="true" void_safety="conformance">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="model" location="..\..\..\..\model\cms_model-safe.ecf"/>
|
||||
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
|
||||
<library name="persitence_mysql" location="..\persistence_mysql-safe.ecf" readonly="false"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<library name="process" location="$ISE_LIBRARY\library\process\process-safe.ecf"/>
|
||||
<cluster name="tests" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1,97 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
TRANSACTION_TEST_SET
|
||||
|
||||
inherit
|
||||
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_user_rollback
|
||||
note
|
||||
testing: "execution/isolated"
|
||||
do
|
||||
connection.begin_transaction
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
assert ("Has user:", user_provider.has_user)
|
||||
connection.rollback
|
||||
assert ("Not has user:", not user_provider.has_user)
|
||||
end
|
||||
|
||||
test_user_node_rollback
|
||||
note
|
||||
testing: "execution/isolated"
|
||||
do
|
||||
connection.begin_transaction
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
assert ("Has user:", user_provider.has_user)
|
||||
node_provider.new_node (default_node)
|
||||
node_provider.add_author (1, 1)
|
||||
assert ("Has one node:", node_provider.count = 1)
|
||||
connection.rollback
|
||||
assert ("Not has user:", not user_provider.has_user)
|
||||
assert ("Not has nodes:", node_provider.count = 0)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
node_provider: NODE_DATA_PROVIDER
|
||||
-- node provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- user provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation Fixture Factories
|
||||
|
||||
default_node: CMS_NODE
|
||||
do
|
||||
Result := custom_node ("Default content", "default summary", "Default")
|
||||
end
|
||||
|
||||
custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE
|
||||
do
|
||||
create Result.make (a_content, a_summary, a_title)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing:"execution/isolated"
|
||||
|
||||
class
|
||||
USER_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
user_provider.new_user ("admin", "admin","admin@admin.com")
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
-- (create {CLEAN_DB}).clean_db(connection)
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_user_exist
|
||||
-- User admin exist
|
||||
do
|
||||
assert ("Not void", attached user_provider.user_by_email ("admin@admin.com"))
|
||||
assert ("Not void", attached user_provider.user (1))
|
||||
assert ("Not void", attached user_provider.user_by_name ("admin"))
|
||||
end
|
||||
|
||||
test_user_not_exist
|
||||
-- Uset test does not exist.
|
||||
do
|
||||
assert ("User by email: Void", user_provider.user_by_email ("test1@test.com") = Void)
|
||||
assert ("User by id: Void", user_provider.user(5) = Void )
|
||||
assert ("User by name: Void", user_provider.user_by_name ("test1") = Void)
|
||||
end
|
||||
|
||||
test_new_user
|
||||
do
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
assert ("Not void", attached user_provider.user_by_email ("test@admin.com"))
|
||||
assert ("Not void", attached user_provider.user (2))
|
||||
assert ("Not void", attached user_provider.user (2) as l_user and then l_user.id = 2 and then l_user.name ~ "test")
|
||||
assert ("Not void", attached user_provider.user_by_name ("test"))
|
||||
end
|
||||
|
||||
test_new_user_with_roles
|
||||
do
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
role_provider.new_role ("Admin")
|
||||
assert ("Empty roles for given user", user_provider.user_roles (1).after)
|
||||
user_provider.add_role (1, 1)
|
||||
assert ("Not empty roles for given user", not user_provider.user_roles (1).after)
|
||||
end
|
||||
|
||||
test_new_user_without_profile
|
||||
do
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
assert ("Empty", user_provider.user_profile (1).new_cursor.after)
|
||||
end
|
||||
|
||||
test_new_user_with_profile
|
||||
local
|
||||
l_profile: CMS_USER_PROFILE
|
||||
l_db_profile: CMS_USER_PROFILE
|
||||
do
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
if attached {CMS_USER} user_provider.user_by_name ("test") as l_user then
|
||||
assert ("Empty", user_provider.user_profile (l_user.id).new_cursor.after)
|
||||
create l_profile.make
|
||||
l_profile.force ("Eiffel", "language")
|
||||
l_profile.force ("Argentina", "country")
|
||||
l_profile.force ("GMT-3", "time zone")
|
||||
user_provider.save_profile (l_user.id, l_profile)
|
||||
l_db_profile := user_provider.user_profile (l_user.id)
|
||||
assert ("Not Empty", not l_db_profile.new_cursor.after)
|
||||
|
||||
assert ("Expected language Eiffel", attached l_db_profile.item ("language") as l_language and then l_language ~ "Eiffel")
|
||||
assert ("Expected time zone GMT-3", attached l_db_profile.item ("time zone") as l_language and then l_language ~ "GMT-3")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- user provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
|
||||
role_provider: ROLE_DATA_PROVIDER
|
||||
-- user provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
note
|
||||
description: "Summary description for {ABSTRACT_DB_TEST}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ABSTRACT_DB_TEST
|
||||
|
||||
|
||||
feature -- Database connection
|
||||
|
||||
connection: DATABASE_CONNECTION_MYSQL
|
||||
-- MYSQL database connection
|
||||
once
|
||||
create Result.login_with_schema ("cms_dev", "root", "")
|
||||
end
|
||||
end
|
||||
129
library/persistence/implementation/mysql/tests/util/clean_db.e
Normal file
129
library/persistence/implementation/mysql/tests/util/clean_db.e
Normal file
@@ -0,0 +1,129 @@
|
||||
note
|
||||
description: "[
|
||||
Setting up database tests
|
||||
1. Put the database in a known state before running your test suite.
|
||||
2. Data reinitialization. For testing in developer sandboxes, something that you should do every time you rebuild the system, you may want to forgo dropping and rebuilding the database in favor of simply reinitializing the source data.
|
||||
You can do this either by erasing all existing data and then inserting the initial data vales back into the database, or you can simple run updates to reset the data values.
|
||||
The first approach is less risky and may even be faster for large amounts of data. - See more at: http://www.agiledata.org/essays/databaseTesting.html#sthash.6yVp35g8.dpuf
|
||||
]"
|
||||
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Database Testing", "src=http://www.agiledata.org/essays/databaseTesting.html", "protocol=uri"
|
||||
testing:"execution/serial"
|
||||
|
||||
class
|
||||
CLEAN_DB
|
||||
|
||||
feature
|
||||
|
||||
clean_db (a_connection: DATABASE_CONNECTION)
|
||||
-- Clean db test.
|
||||
local
|
||||
l_parameters: STRING_TABLE[STRING]
|
||||
do
|
||||
create l_parameters.make (0)
|
||||
|
||||
a_connection.begin_transaction
|
||||
|
||||
-- Clean Profiles
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_user_profiles, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- Clean Permissions
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_permissions, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
|
||||
-- Clean Users Nodes
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_users_nodes, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
|
||||
-- Clean Users Roles
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_users_roles, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- Clean Roles
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_roles, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- Clean Nodes
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_nodes, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- Clean Users
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_users, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
|
||||
-- Reset Autoincremente
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_users_autoincrement, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_nodes_autoincrement, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_roles_autoincrement, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_permissions_autoincrement, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_profiles_autoincrement, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
a_connection.commit
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature -- Database Hanlder
|
||||
|
||||
db_handler (a_connection: DATABASE_CONNECTION): DATABASE_HANDLER
|
||||
-- Db handler
|
||||
once
|
||||
create {DATABASE_HANDLER_IMPL} Result.make (a_connection)
|
||||
end
|
||||
|
||||
|
||||
feature -- Sql delete queries
|
||||
|
||||
Sql_delete_users: STRING = "delete from Users"
|
||||
-- Clean Users.
|
||||
|
||||
Sql_delete_nodes: STRING = "delete from Nodes"
|
||||
-- Clean Nodes.
|
||||
|
||||
Sql_delete_roles: STRING = "delete from Roles"
|
||||
-- Clean Roles.
|
||||
|
||||
Sql_delete_permissions: STRING = "delete from Permissions"
|
||||
-- Clean Permissions.
|
||||
|
||||
Sql_delete_users_roles: STRING = "delete from Users_roles"
|
||||
-- Clean User roles.
|
||||
|
||||
Sql_delete_user_profiles: STRING = "delete from profiles"
|
||||
-- Clean profiles.
|
||||
|
||||
Sql_delete_users_nodes: STRING = "delete from users_nodes"
|
||||
|
||||
Rest_users_autoincrement: STRING = "ALTER TABLE Users AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement
|
||||
|
||||
Rest_nodes_autoincrement: STRING = "ALTER TABLE Nodes AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement.
|
||||
|
||||
Rest_roles_autoincrement: STRING = "ALTER TABLE Roles AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement.
|
||||
|
||||
Rest_permissions_autoincrement: STRING = "ALTER TABLE Permissions AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement.
|
||||
|
||||
Rest_profiles_autoincrement: STRING = "ALTER TABLE Profiles AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement.
|
||||
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="persistence_sqlite" uuid="8FD9D3B3-5FC1-495F-A05D-0205EC966841" library_target="persistence_sqlite">
|
||||
<target name="persistence_sqlite">
|
||||
<root all_classes="true"/>
|
||||
<option warning="true" void_safety="all">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="console_application" value="true"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
|
||||
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="layout" location="..\..\..\layout\layout-safe.ecf"/>
|
||||
<library name="model" location="..\..\..\model\cms_model-safe.ecf"/>
|
||||
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging-safe.ecf"/>
|
||||
<library name="mysql" location="$ISE_LIBRARY\library\store\dbms\rdbms\mysql\mysql-safe.ecf"/>
|
||||
<library name="odbc" location="$ISE_LIBRARY\library\store\dbms\rdbms\odbc\odbc-safe.ecf"/>
|
||||
<library name="store" location="$ISE_LIBRARY\library\store\store-safe.ecf" readonly="false"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||
<cluster name="common" location="..\common\" recursive="true"/>
|
||||
<cluster name="interface" location="..\..\interface\" recursive="true"/>
|
||||
<cluster name="persistence_sqlite" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1 @@
|
||||
Added Stored Procedures
|
||||
@@ -0,0 +1,61 @@
|
||||
-- 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;
|
||||
14
library/persistence/implementation/sqlite/scripts/tables.sql
Normal file
14
library/persistence/implementation/sqlite/scripts/tables.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
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)
|
||||
);
|
||||
@@ -0,0 +1,272 @@
|
||||
note
|
||||
description: "Summary description for {CMS_STORAGE_MYSQL}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_STORAGE_SQLITE
|
||||
|
||||
inherit
|
||||
|
||||
CMS_STORAGE
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_connection: DATABASE_CONNECTION)
|
||||
--
|
||||
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)
|
||||
post_node_provider_execution
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
|
||||
feature -- Access: user
|
||||
|
||||
has_user: BOOLEAN
|
||||
-- Has any user?
|
||||
do
|
||||
Result := user_provider.has_user
|
||||
post_user_provider_execution
|
||||
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)
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
|
||||
do
|
||||
Result := user_provider.user_by_name (a_name)
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
|
||||
do
|
||||
Result := user_provider.user_by_email (a_email)
|
||||
post_user_provider_execution
|
||||
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
|
||||
end
|
||||
post_user_provider_execution
|
||||
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
|
||||
user_provider.new_user (a_user.name, l_password, l_email)
|
||||
else
|
||||
-- set error
|
||||
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
|
||||
post_node_provider_execution
|
||||
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
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
node (a_id: INTEGER_64): detachable CMS_NODE
|
||||
--
|
||||
do
|
||||
Result := node_provider.node (a_id)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
|
||||
feature -- Node
|
||||
|
||||
save_node (a_node: CMS_NODE)
|
||||
-- Add a new node
|
||||
do
|
||||
node_provider.new_node (a_node)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
delete_node (a_id: INTEGER_64)
|
||||
do
|
||||
node_provider.delete_node (a_id)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE)
|
||||
do
|
||||
node_provider.update_node (a_node)
|
||||
post_node_provider_execution
|
||||
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)
|
||||
post_node_provider_execution
|
||||
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)
|
||||
post_node_provider_execution
|
||||
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)
|
||||
post_node_provider_execution
|
||||
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} -- Post process
|
||||
|
||||
post_node_provider_execution
|
||||
do
|
||||
if node_provider.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached node_provider.last_error then
|
||||
set_last_error_from_handler (node_provider.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
post_user_provider_execution
|
||||
do
|
||||
if user_provider.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached user_provider.last_error then
|
||||
set_last_error_from_handler (user_provider.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
node_provider: NODE_DATA_PROVIDER
|
||||
-- Node Data provider.
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- User Data provider.
|
||||
|
||||
end
|
||||
@@ -0,0 +1,145 @@
|
||||
note
|
||||
description: "Object that handle a database connection for ODBC"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATABASE_CONNECTION_MYSQL
|
||||
|
||||
inherit
|
||||
|
||||
DATABASE_CONNECTION
|
||||
redefine
|
||||
db_application
|
||||
end
|
||||
|
||||
create
|
||||
make, make_common, make_basic, login_with_connection_string, login_with_schema
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make_common
|
||||
-- Create a database handler for MYSQL with common settings.
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
create db_application.login (username, password)
|
||||
|
||||
if not l_retried then
|
||||
db_application.set_hostname (hostname)
|
||||
db_application.set_data_source (database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
set_successful
|
||||
else
|
||||
create db_control.make
|
||||
end
|
||||
rescue
|
||||
create db_control.make
|
||||
set_last_error_from_exception ("Connection execution")
|
||||
log.write_critical (generator + ".make_common:" + last_error_message)
|
||||
if is_connected then
|
||||
disconnect
|
||||
end
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
make_basic (a_database_name: STRING)
|
||||
-- Create a database handler and
|
||||
-- set database_name to `a_database_name'.
|
||||
local
|
||||
l_retried: BOOLEAN
|
||||
do
|
||||
create db_application.login (username, password)
|
||||
|
||||
if not l_retried then
|
||||
db_application.set_hostname (hostname)
|
||||
db_application.set_data_source (a_database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
set_successful
|
||||
else
|
||||
create db_control.make
|
||||
end
|
||||
rescue
|
||||
create db_control.make
|
||||
set_last_error_from_exception ("Connection execution")
|
||||
log.write_critical (generator + ".make_common:" + last_error_message)
|
||||
if is_connected then
|
||||
disconnect
|
||||
end
|
||||
l_retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
|
||||
|
||||
-- Create a database handler for ODBC and set `username' to `a_username',
|
||||
-- `password' to `a_password'
|
||||
-- `database_name' to `a_database_name'
|
||||
-- `connection' to `a_connection'
|
||||
do
|
||||
create db_application.login (a_username, a_password)
|
||||
db_application.set_hostname (a_hostname)
|
||||
db_application.set_data_source (a_database_name)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := connection
|
||||
if keep_connection then
|
||||
connect
|
||||
end
|
||||
end
|
||||
|
||||
login_with_connection_string (a_string: STRING)
|
||||
-- Login with `a_connection_string'and immediately connect to database.
|
||||
local
|
||||
l_string: LIST[STRING]
|
||||
l_server: STRING
|
||||
l_port: STRING
|
||||
l_schema: STRING
|
||||
l_user: STRING
|
||||
l_password: STRING
|
||||
do
|
||||
l_string := a_string.split (';')
|
||||
l_server := l_string.at (2).split ('=').at (2)
|
||||
l_port := l_string.at (3).split ('=').at (2)
|
||||
l_schema := l_string.at (4).split ('=').at (2)
|
||||
l_user := l_string.at (5).split ('=').at (2)
|
||||
l_password := l_string.at (6).split ('=').at (2)
|
||||
|
||||
create db_application
|
||||
db_application.set_application (l_schema)
|
||||
db_application.set_hostname (l_server + ":" + l_port)
|
||||
db_application.login_and_connect (l_user, l_password)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
|
||||
end
|
||||
|
||||
login_with_schema (a_schema: STRING; a_username: STRING; a_password: STRING)
|
||||
-- Login with `a_connection_string'and immediately connect to database.
|
||||
do
|
||||
create db_application
|
||||
db_application.set_application (a_schema)
|
||||
db_application.login_and_connect (a_username, a_password)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
end
|
||||
|
||||
feature -- Databse Connection
|
||||
|
||||
db_application: DATABASE_APPL [MYSQL]
|
||||
-- Database application.
|
||||
|
||||
end
|
||||
@@ -0,0 +1,289 @@
|
||||
note
|
||||
description: "Database access for node uses cases."
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
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)
|
||||
post_execution
|
||||
end
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Db handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_successful: BOOLEAN
|
||||
-- Is the last execution sucessful?
|
||||
do
|
||||
Result := db_handler.successful
|
||||
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)
|
||||
post_execution
|
||||
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)
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
post_execution
|
||||
-- Post database execution.
|
||||
do
|
||||
if db_handler.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached db_handler.last_error then
|
||||
set_last_error_from_handler (db_handler.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,206 @@
|
||||
note
|
||||
description: "Summary description for {USER_DATA_PROVIDER}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
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)
|
||||
post_execution
|
||||
end
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Db handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_successful: BOOLEAN
|
||||
-- Is the last execution sucessful?
|
||||
do
|
||||
Result := db_handler.successful
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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
|
||||
post_execution
|
||||
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.
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
post_execution
|
||||
-- Post database execution.
|
||||
do
|
||||
if db_handler.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached db_handler.last_error then
|
||||
set_last_error_from_handler (db_handler.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
26
library/persistence/implementation/sqlite/tests/Readme.md
Normal file
26
library/persistence/implementation/sqlite/tests/Readme.md
Normal file
@@ -0,0 +1,26 @@
|
||||
SQLite ODBC.
|
||||
|
||||
Install the odbc driver from http://www.ch-werner.de/sqliteodbc/
|
||||
|
||||
Current version
|
||||
sqliteodbc.exe -- Win32
|
||||
sqliteodbc_w64.exe -- Win64
|
||||
|
||||
|
||||
Test the ODBC driver using Firefox SQLite DBManager https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/
|
||||
|
||||
1. Open the odbc manger from Windows, create a new database using the SQLite3 ODBC driver and then open it from Firefox.
|
||||
|
||||
|
||||
EiffelStore + SQLiteODBC.
|
||||
|
||||
Connection String: https://www.connectionstrings.com/sqlite3-odbc-driver/
|
||||
|
||||
"Driver=SQLite3 ODBC Driver;Database=./cms_lite.db;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
|
||||
|
||||
Edit the database location based on your system.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description : "tests application root class"
|
||||
date : "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision : "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
ARGUMENTS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
local
|
||||
user: USER_DATA_PROVIDER
|
||||
node: NODE_DATA_PROVIDER
|
||||
l_security: SECURITY_PROVIDER
|
||||
do
|
||||
-- Change the path.
|
||||
create connection.login_with_connection_string ("Driver=SQLite3 ODBC Driver;Database=./cms_lite.db;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;")
|
||||
create user.make (connection)
|
||||
user.new_user ("test", "test", "test")
|
||||
end
|
||||
|
||||
connection: DATABASE_CONNECTION_ODBC
|
||||
|
||||
end
|
||||
BIN
library/persistence/implementation/sqlite/tests/cms_lite.db
Normal file
BIN
library/persistence/implementation/sqlite/tests/cms_lite.db
Normal file
Binary file not shown.
@@ -0,0 +1,225 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
NODE_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_new_node
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
node_provider.new_node (default_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached node_provider.node (1))
|
||||
-- Not exist node with id 2
|
||||
assert ("Not exist node with id 2", node_provider.node (2) = Void)
|
||||
end
|
||||
|
||||
|
||||
test_update_node
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node (content and summary)
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
l_un.set_content ("<h1>Updating test node udpate </h1>")
|
||||
l_un.set_summary ("updating summary")
|
||||
node_provider.update_node (l_un)
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_node.content) and then not (ll_node.summary ~ l_node.summary) and then ll_node.title ~ l_node.title )
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title )
|
||||
end
|
||||
|
||||
-- Update node (content and summary and title)
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
l_un.set_content ("<h1>Updating test node udpate </h1>")
|
||||
l_un.set_summary ("updating summary")
|
||||
l_un.set_title ("Updating Test case")
|
||||
node_provider.update_node (l_un)
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_node.content) and then not (ll_node.summary ~ l_node.summary) and then not (ll_node.title ~ l_node.title) )
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title )
|
||||
end
|
||||
end
|
||||
|
||||
test_update_title
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node title
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
node_provider.update_node_title (l_un.id, "New Title")
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then ll_node.summary ~ l_un.summary and then not ( ll_node.title ~ l_un.title) and then ll_node.title ~ "New Title" )
|
||||
end
|
||||
end
|
||||
|
||||
test_update_summary
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node summary
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
node_provider.update_node_summary (l_un.id,"New Summary")
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_un.content and then not (ll_node.summary ~ l_un.summary) and then ll_node.summary ~ "New Summary" and then ll_node.title ~ l_un.title)
|
||||
end
|
||||
end
|
||||
|
||||
test_update_content
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Update node content
|
||||
|
||||
if attached {CMS_NODE} node_provider.node (1) as l_un then
|
||||
node_provider.update_node_content (l_un.id,"New Content")
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_un.content) and then ll_node.content ~ "New Content" and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_delete_node
|
||||
local
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
l_node := custom_node ("<h1> test node udpate </h1>", "Update node", "Test case update")
|
||||
node_provider.new_node (l_node)
|
||||
assert ("Not empty Nodes after new_node", not node_provider.nodes.after)
|
||||
-- Exist node with id 1
|
||||
assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then ll_node.content ~ l_node.content and then ll_node.summary ~ l_node.summary and then ll_node.title ~ l_node.title )
|
||||
|
||||
-- Delte node 1
|
||||
|
||||
node_provider.delete_node (1)
|
||||
assert ("Node does not exist", node_provider.node (1) = Void)
|
||||
end
|
||||
|
||||
test_recent_nodes
|
||||
-- Content_10, Summary_10, Title_10
|
||||
-- Content_9, Summary_9, Title_9
|
||||
-- ..
|
||||
-- Content_1, Summary_1, Title_1
|
||||
local
|
||||
i : INTEGER
|
||||
do
|
||||
assert ("Empty Nodes", node_provider.nodes.after)
|
||||
across 1 |..| 10 as c loop
|
||||
node_provider.new_node (custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out))
|
||||
end
|
||||
|
||||
-- Scenario (0,10) rows, recents (10 down to 1)
|
||||
i := 10
|
||||
across node_provider.recent_nodes (0, 10) as c loop
|
||||
assert ("Same id:" + i.out, c.item.id = i)
|
||||
i := i - 1
|
||||
end
|
||||
|
||||
-- Scenario (5, 10) rows, recent nodes (5 down to 1)
|
||||
i := 5
|
||||
across node_provider.recent_nodes (5, 10) as c loop
|
||||
assert ("Same id:" + i.out, c.item.id = i)
|
||||
i := i - 1
|
||||
end
|
||||
|
||||
-- Scenario (9,10) rows, recent node 1
|
||||
i := 1
|
||||
across node_provider.recent_nodes (9, 10) as c loop
|
||||
assert ("Same id:" + i.out, c.item.id = i)
|
||||
i := i - 1
|
||||
end
|
||||
|
||||
-- Scenrario 10..10 empty
|
||||
assert ("Empty", node_provider.recent_nodes (10, 10).after)
|
||||
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
node_provider: NODE_DATA_PROVIDER
|
||||
-- node provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation Fixture Factories
|
||||
|
||||
default_node: CMS_NODE
|
||||
do
|
||||
Result := custom_node ("Default content", "default summary", "Default")
|
||||
end
|
||||
|
||||
custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE
|
||||
do
|
||||
create Result.make (a_content, a_summary, a_title)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,323 @@
|
||||
note
|
||||
description: "Summary description for {STORAGE_TEST_SET}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
STORAGE_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_has_user
|
||||
do
|
||||
assert ("Not has user", not storage.has_user)
|
||||
end
|
||||
|
||||
test_all_users
|
||||
do
|
||||
assert ("to implement all_users", False)
|
||||
end
|
||||
|
||||
test_user_by_id_not_exist
|
||||
do
|
||||
assert ("User does not exist", storage.user_by_id (1) = Void)
|
||||
end
|
||||
|
||||
test_user_by_name_not_exist
|
||||
do
|
||||
assert ("User does not exist", storage.user_by_name ("test") = Void)
|
||||
end
|
||||
|
||||
test_user_by_email_not_exist
|
||||
do
|
||||
assert ("User does not exist", storage.user_by_name ("test@test.com") = Void)
|
||||
end
|
||||
|
||||
test_user_with_bad_id
|
||||
local
|
||||
l_retry: BOOLEAN
|
||||
l_user: detachable CMS_USER
|
||||
do
|
||||
if not l_retry then
|
||||
l_user := storage.user_by_id (0)
|
||||
assert ("Precondition does not get the wrong value", False)
|
||||
else
|
||||
assert ("Expected precondition violation", True)
|
||||
end
|
||||
rescue
|
||||
l_retry := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_user_with_bad_name_empty
|
||||
local
|
||||
l_retry: BOOLEAN
|
||||
l_user: detachable CMS_USER
|
||||
do
|
||||
if not l_retry then
|
||||
l_user := storage.user_by_name ("")
|
||||
assert ("Precondition does not get the wrong value", False)
|
||||
else
|
||||
assert ("Expected precondition violation", True)
|
||||
end
|
||||
rescue
|
||||
l_retry := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_user_with_bad_email_empty
|
||||
local
|
||||
l_retry: BOOLEAN
|
||||
l_user: detachable CMS_USER
|
||||
do
|
||||
if not l_retry then
|
||||
l_user := storage.user_by_email ("")
|
||||
assert ("Precondition does not get the wrong value", False)
|
||||
else
|
||||
assert ("Expected precondition violation", True)
|
||||
end
|
||||
rescue
|
||||
l_retry := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_save_user
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
end
|
||||
|
||||
test_user_by_id
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
if attached {CMS_USER} storage.user_by_id (1) as l_user then
|
||||
assert ("Exist", True)
|
||||
assert ("User test", l_user.name ~ "test")
|
||||
assert ("User id = 1", l_user.id = 1)
|
||||
else
|
||||
assert ("Wrong Implementation", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_user_by_name
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
if attached {CMS_USER} storage.user_by_name ("test") as l_user then
|
||||
assert ("Exist", True)
|
||||
assert ("User nane: test", l_user.name ~ "test")
|
||||
else
|
||||
assert ("Wrong Implementation", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_user_by_email
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user", storage.has_user)
|
||||
if attached {CMS_USER} storage.user_by_email ("test@test.com") as l_user then
|
||||
assert ("Exist", True)
|
||||
assert ("User email: test@test.com", l_user.email ~ "test@test.com")
|
||||
else
|
||||
assert ("Wrong Implementation", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_invalid_credential
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user test", attached storage.user_by_name ("test"))
|
||||
assert ("Wrong password", not storage.is_valid_credential ("test", "test"))
|
||||
assert ("Wrong user", not storage.is_valid_credential ("test1", "test"))
|
||||
end
|
||||
|
||||
test_valid_credential
|
||||
do
|
||||
storage.save_user (default_user)
|
||||
assert ("Has user test", attached storage.user_by_name ("test"))
|
||||
assert ("Valid password", storage.is_valid_credential ("test", "password"))
|
||||
end
|
||||
|
||||
test_recent_nodes_empty
|
||||
do
|
||||
assert ("No recent nodes", storage.recent_nodes (0, 10).is_empty)
|
||||
end
|
||||
|
||||
test_recent_nodes
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
do
|
||||
across 1 |..| 10 as c loop
|
||||
storage.save_node (custom_node ("Content_" + c.item.out, "Summary_" + c.item.out, "Title_" + c.item.out))
|
||||
end
|
||||
l_nodes := storage.recent_nodes (0, 10)
|
||||
assert ("10 recent nodes", l_nodes.count = 10)
|
||||
assert ("First node id=10", l_nodes.first.id = 10)
|
||||
assert ("Last node id=1", l_nodes.last.id = 1)
|
||||
|
||||
|
||||
l_nodes := storage.recent_nodes (5, 10)
|
||||
assert ("5 recent nodes", l_nodes.count = 5)
|
||||
assert ("First node id=5", l_nodes.first.id = 5)
|
||||
assert ("Last node id=1", l_nodes.last.id = 1)
|
||||
|
||||
l_nodes := storage.recent_nodes (9, 10)
|
||||
assert ("1 recent nodes", l_nodes.count = 1)
|
||||
assert ("First node id=1", l_nodes.first.id = 1)
|
||||
assert ("Last node id=1", l_nodes.last.id = 1)
|
||||
|
||||
l_nodes := storage.recent_nodes (10, 10)
|
||||
assert ("Is empty", l_nodes.is_empty)
|
||||
end
|
||||
|
||||
test_node_does_not_exist
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
do
|
||||
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 ("Not exist node id: 12", storage.node (12) = Void)
|
||||
end
|
||||
|
||||
test_node
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
do
|
||||
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 ("Node id: 10", attached storage.node (10) as l_node and then l_node.title ~ "Title_10" )
|
||||
end
|
||||
|
||||
test_update_node
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
storage.save_node (custom_node ("Content", "Summary", "Title"))
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
l_node := ll_node.twin
|
||||
l_node.set_content ("New Content")
|
||||
l_node.set_summary ("New Summary")
|
||||
l_node.set_title("New Title")
|
||||
|
||||
-- storage.update_node (l_node)
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then not (u_node.title ~ ll_node.title) and then not (u_node.content ~ ll_node.content) and then not (u_node.summary ~ ll_node.summary))
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_title
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
storage.save_node (custom_node ("Content", "Summary", "Title"))
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
-- storage.update_node_title (ll_node.id, "New Title")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then not (u_node.title ~ ll_node.title) and then u_node.content ~ ll_node.content and then u_node.summary ~ ll_node.summary)
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_summary
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
storage.save_node (custom_node ("Content", "Summary", "Title"))
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
-- storage.update_node_summary (ll_node.id, "New Summary")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then u_node.title ~ ll_node.title and then u_node.content ~ ll_node.content and then not (u_node.summary ~ ll_node.summary))
|
||||
end
|
||||
end
|
||||
|
||||
test_update_node_content
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
l_node: CMS_NODE
|
||||
do
|
||||
storage.save_node (custom_node ("Content", "Summary", "Title"))
|
||||
if attached {CMS_NODE} storage.node (1) as ll_node then
|
||||
-- storage.update_node_content (ll_node.id, "New Content")
|
||||
assert ("Updated", attached {CMS_NODE} storage.node (1) as u_node and then u_node.title ~ ll_node.title and then not (u_node.content ~ ll_node.content) and then u_node.summary ~ ll_node.summary)
|
||||
end
|
||||
end
|
||||
|
||||
test_delete_node
|
||||
local
|
||||
l_nodes: LIST[CMS_NODE]
|
||||
do
|
||||
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 ("Exist node id: 10", attached storage.node (10) as l_node and then l_node.title ~ "Title_10" )
|
||||
storage.delete_node (10)
|
||||
assert ("Not exist node id: 10", storage.node (10) = Void)
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
storage: CMS_STORAGE
|
||||
-- Storage
|
||||
once
|
||||
create {CMS_STORAGE_SQLITE}Result.make (connection)
|
||||
end
|
||||
|
||||
feature {NONE} -- Fixture Factory: Users
|
||||
|
||||
default_user: CMS_USER
|
||||
do
|
||||
Result := custom_user ("test", "password", "test@test.com")
|
||||
end
|
||||
|
||||
custom_user (a_name, a_password, a_email: READABLE_STRING_32): CMS_USER
|
||||
do
|
||||
create Result.make (a_name)
|
||||
Result.set_password (a_password)
|
||||
Result.set_email (a_email)
|
||||
end
|
||||
|
||||
feature {NONE} -- Fixture Factories: Nodes
|
||||
|
||||
default_node: CMS_NODE
|
||||
do
|
||||
Result := custom_node ("Default content", "default summary", "Default")
|
||||
end
|
||||
|
||||
custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE
|
||||
do
|
||||
create Result.make (a_content, a_summary, a_title)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="tests" uuid="FE27C81D-3F7D-4E46-992B-55F4BBDA4F8B">
|
||||
<target name="tests">
|
||||
<root class="APPLICATION" feature="make"/>
|
||||
<option warning="true" void_safety="conformance">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
|
||||
<library name="persitence_sqlite" location="..\persistence_sqlite-safe.ecf" readonly="false"/>
|
||||
<library name="process" location="$ISE_LIBRARY\library\process\process-safe.ecf"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<cluster name="tests" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1,78 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
USER_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
user_provider.new_user ("admin", "admin","admin@admin.com")
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_user_exist
|
||||
-- User admin exist
|
||||
do
|
||||
assert ("Not void", attached user_provider.user_by_email ("admin@admin.com"))
|
||||
assert ("Not void", attached user_provider.user (1))
|
||||
assert ("Not void", attached user_provider.user_by_name ("admin"))
|
||||
end
|
||||
|
||||
test_user_not_exist
|
||||
-- Uset test does not exist.
|
||||
do
|
||||
assert ("Void", user_provider.user_by_email ("test@admin.com") = Void)
|
||||
assert ("Void", user_provider.user(2) = Void )
|
||||
assert ("Void", user_provider.user_by_name ("test") = Void)
|
||||
end
|
||||
|
||||
test_new_user
|
||||
do
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
assert ("Not void", attached user_provider.user_by_email ("test@admin.com"))
|
||||
assert ("Not void", attached user_provider.user (2))
|
||||
assert ("Not void", attached user_provider.user (2) as l_user and then l_user.id = 2 and then l_user.name ~ "test")
|
||||
assert ("Not void", attached user_provider.user_by_name ("test"))
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- user provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
note
|
||||
description: "Summary description for {ABSTRACT_DB_TEST}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ABSTRACT_DB_TEST
|
||||
|
||||
|
||||
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")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,66 @@
|
||||
note
|
||||
description: "[
|
||||
Setting up database tests
|
||||
1. Put the database in a known state before running your test suite.
|
||||
2. Data reinitialization. For testing in developer sandboxes, something that you should do every time you rebuild the system, you may want to forgo dropping and rebuilding the database in favor of simply reinitializing the source data.
|
||||
You can do this either by erasing all existing data and then inserting the initial data vales back into the database, or you can simple run updates to reset the data values.
|
||||
The first approach is less risky and may even be faster for large amounts of data. - See more at: http://www.agiledata.org/essays/databaseTesting.html#sthash.6yVp35g8.dpuf
|
||||
]"
|
||||
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Database Testing", "src=http://www.agiledata.org/essays/databaseTesting.html", "protocol=uri"
|
||||
|
||||
class
|
||||
CLEAN_DB
|
||||
|
||||
feature
|
||||
|
||||
clean_db (a_connection: DATABASE_CONNECTION)
|
||||
-- Clean db test.
|
||||
local
|
||||
l_parameters: STRING_TABLE[STRING]
|
||||
do
|
||||
create l_parameters.make (0)
|
||||
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_nodes, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- Clean Users
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_users, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- -- Reset Autoincremente
|
||||
-- db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_users_autoincrement, l_parameters))
|
||||
-- db_handler(a_connection).execute_change
|
||||
|
||||
-- db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_nodes_autoincrement, l_parameters))
|
||||
-- db_handler(a_connection).execute_change
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature -- Database Hanlder
|
||||
|
||||
db_handler (a_connection: DATABASE_CONNECTION): DATABASE_HANDLER
|
||||
-- Db handler
|
||||
once
|
||||
create {DATABASE_HANDLER_IMPL} Result.make (a_connection)
|
||||
end
|
||||
|
||||
|
||||
feature -- Sql delete queries
|
||||
|
||||
Sql_delete_users: STRING = "delete from Users"
|
||||
-- Clean Users.
|
||||
|
||||
Sql_delete_nodes: STRING = "delete from Nodes"
|
||||
-- Clean Nodes.
|
||||
|
||||
Rest_users_autoincrement: STRING = "ALTER TABLE Users AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement
|
||||
|
||||
Rest_nodes_autoincrement: STRING = "ALTER TABLE Nodes AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement.
|
||||
|
||||
end
|
||||
261
library/persistence/interface/cms_storage.e
Normal file
261
library/persistence/interface/cms_storage.e
Normal file
@@ -0,0 +1,261 @@
|
||||
|
||||
note
|
||||
description : "[
|
||||
CMS interface to storage
|
||||
]"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
deferred class
|
||||
CMS_STORAGE
|
||||
|
||||
inherit
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
do
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
-- 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'
|
||||
-- deferred
|
||||
-- end
|
||||
|
||||
-- custom_value (a_name: READABLE_STRING_8; a_type: READABLE_STRING_8): detachable TABLE_ITERABLE [READABLE_STRING_8, STRING_8]
|
||||
-- -- Data for name `a_name' and type `a_type'.
|
||||
-- deferred
|
||||
-- end
|
||||
|
||||
-- custom_value_names_where (a_where_key, a_where_value: READABLE_STRING_8; a_type: READABLE_STRING_8): detachable LIST [READABLE_STRING_8]
|
||||
-- -- Names where custom value has item `a_where_key' same as `a_where_value' for type `a_type'.
|
||||
-- deferred
|
||||
-- end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user