From 56510c02a93997ef87a90639c9ef8c8ffe3e9e23 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 30 Mar 2017 12:34:35 -0500 Subject: [PATCH] Progress: improve access control database structure and other changes Numerous changes, but there has been a huge focus on access control changes. It occurred to me that if an account was locked or deleted, then they should be denied access to all of the views (with exception of the current user views). This required a notable structural change. The tables are now stored in the s_table schema. In case accounts get locked, even administer accounts, access should be disabled. I did not get the time to convert all of the administer and manager roles to be restricted to views but will eventually do so. --- common/base/classes/base_database.php | 7 +- common/base/classes/base_error.php | 26 ++ .../base/classes/base_error_messages_english.php | 8 +- .../base/classes/base_error_messages_japanese.php | 8 +- common/base/classes/base_form.php | 8 +- common/base/classes/base_mime.php | 6 +- common/base/classes/base_session.php | 8 +- .../sql/reservation/reservation-associations.sql | 14 +- database/sql/reservation/reservation-dates.sql | 8 +- database/sql/reservation/reservation-fields.sql | 14 +- database/sql/reservation/reservation-files.sql | 95 ++++++ database/sql/reservation/reservation-first.sql | 1 + database/sql/reservation/reservation-groups.sql | 85 +++-- database/sql/reservation/reservation-last.sql | 157 +++++----- database/sql/reservation/reservation-legal.sql | 14 +- .../sql/reservation/reservation-log_groups.sql | 8 +- .../sql/reservation/reservation-log_problems.sql | 10 +- database/sql/reservation/reservation-log_types.sql | 67 ++-- database/sql/reservation/reservation-log_users.sql | 16 +- database/sql/reservation/reservation-main.sql | 12 +- database/sql/reservation/reservation-paths.sql | 22 +- database/sql/reservation/reservation-requests.sql | 46 +-- .../sql/reservation/reservation-statistics.sql | 4 +- database/sql/reservation/reservation-types.sql | 10 +- database/sql/reservation/reservation-users.sql | 54 ++-- database/sql/reservation/reservation-workflow.sql | 2 +- examples/test.php | 348 +++++++++++++++------ program/reservation/index.php | 8 +- program/reservation/reservation_database.php | 257 ++++++++++----- program/reservation/reservation_paths.php | 145 +++++---- .../source/php/sessionize_accounts-server.php | 10 +- 31 files changed, 977 insertions(+), 501 deletions(-) create mode 100644 database/sql/reservation/reservation-files.sql diff --git a/common/base/classes/base_database.php b/common/base/classes/base_database.php index d250e06..3caf269 100644 --- a/common/base/classes/base_database.php +++ b/common/base/classes/base_database.php @@ -24,6 +24,9 @@ * - A reason against persistent connections is the inability to directly close them. * - This is a major weakness and may prevent me from using this persistent connection design (much testing is required). * + * To get the current roles assigned to the user currently logged into the database is: + * select pr.rolname from pg_auth_members pam inner join pg_roles pr on (pam.roleid = pr.oid) inner join pg_roles pr_u on (pam.member = pr_u.oid) where pr_u.rolname = user; + * * @see: http://php.net/manual/en/features.persistent-connections.php */ @@ -2467,6 +2470,7 @@ class c_base_database_result extends c_base_return_resource { * * @return c_base_return_status|c_base_return_value * The value on success, FALSE otherwise. + * FALSE with the error bit set is returned on error. * * @see: pg_fetch_row() */ @@ -2509,7 +2513,8 @@ class c_base_database_result extends c_base_return_resource { * - PGSQL_DIAG_SOURCE_FUNCTION * * @return c_base_return_status|c_base_return_string - * String is returned if found, a NULL is returned if not found, and FALSE is returned on error (with error flag set). + * String is returned if found and a NULL is returned if not found. + * FALSE with the error bit set is returned on error. * * @see: pg_result_error() * @see: pg_result_error_field() diff --git a/common/base/classes/base_error.php b/common/base/classes/base_error.php index d493b30..a8eb844 100644 --- a/common/base/classes/base_error.php +++ b/common/base/classes/base_error.php @@ -516,6 +516,32 @@ interface i_base_error_messages { /** + * Converts a given error message into a processed string. + * + * @param c_base_error $code + * The error message code. + * @param bool $arguments + * (optional) When TRUE, argument placeholders are added. + * When FALSE, no placeholders are provided. + * All placeholders should begin with a single colon ':'. + * @param bool $function_name + * (optional) When TRUE, the function name is included with the message. + * When FALSE, no funciton name is provided. + * @param null|string $additional_message + * (optional) Any additional messages to display. + * @param bool $use_html + * (optional) When TRUE, the message is escaped and then wrapped in HTML. + * When FALSE, no HTML wrapping or escaping is peformed. + * + * @return c_base_return_string + * A processed string is returned on success. + * FALSE with error bit set is returned on error. + * + * @see: s_get_message() + */ + static function s_render_error_message($error, $arguments = TRUE, $function_name = FALSE, $additional_message = NULL, $html = TRUE); + + /** * Returns a standard error message associated with the given code. * * @param int $code diff --git a/common/base/classes/base_error_messages_english.php b/common/base/classes/base_error_messages_english.php index 3deedba..d1eb3a8 100644 --- a/common/base/classes/base_error_messages_english.php +++ b/common/base/classes/base_error_messages_english.php @@ -24,6 +24,8 @@ final class c_base_error_messages_english implements i_base_error_messages { * @param bool $function_name * (optional) When TRUE, the function name is included with the message. * When FALSE, no funciton name is provided. + * @param null|string $additional_message + * (optional) Any additional messages to display. * @param bool $use_html * (optional) When TRUE, the message is escaped and then wrapped in HTML. * When FALSE, no HTML wrapping or escaping is peformed. @@ -34,7 +36,7 @@ final class c_base_error_messages_english implements i_base_error_messages { * * @see: s_get_message() */ - static function s_render_error_message($error, $arguments = TRUE, $function_name = FALSE, $html = TRUE) { + static function s_render_error_message($error, $arguments = TRUE, $function_name = FALSE, $additional_message = NULL, $html = TRUE) { if (!($error instanceof c_base_error)) { return c_base_return_string::s_new(''); } @@ -46,6 +48,10 @@ final class c_base_error_messages_english implements i_base_error_messages { } $message = self::s_get_message($code, $arguments, $function_name)->get_value_exact(); + if (is_string($additional_message)) { + $message .= $additional_message; + } + if (empty($message)) { unset($message); unset($code); diff --git a/common/base/classes/base_error_messages_japanese.php b/common/base/classes/base_error_messages_japanese.php index 413e438..0fa51d5 100644 --- a/common/base/classes/base_error_messages_japanese.php +++ b/common/base/classes/base_error_messages_japanese.php @@ -29,6 +29,8 @@ final class c_base_error_messages_japanese implements i_base_error_messages { * @param bool $function_name * (optional) When TRUE, the function name is included with the message. * When FALSE, no funciton name is provided. + * @param null|string $additional_message + * (optional) Any additional messages to display. * @param bool $use_html * (optional) When TRUE, the message is escaped and then wrapped in HTML. * When FALSE, no HTML wrapping or escaping is peformed. @@ -39,7 +41,7 @@ final class c_base_error_messages_japanese implements i_base_error_messages { * * @see: s_get_message() */ - static function s_render_error_message($error, $arguments = TRUE, $function_name = FALSE, $html = TRUE) { + static function s_render_error_message($error, $arguments = TRUE, $function_name = FALSE, $additional_message = NULL, $html = TRUE) { if (!($error instanceof c_base_error)) { return c_base_return_string::s_new(''); } @@ -51,6 +53,10 @@ final class c_base_error_messages_japanese implements i_base_error_messages { } $message = self::s_get_message($code, $arguments, $function_name)->get_value_exact(); + if (is_string($additional_message)) { + $message .= $additional_message; + } + if (empty($message)) { unset($message); unset($code); diff --git a/common/base/classes/base_form.php b/common/base/classes/base_form.php index ecb6736..59f1f30 100644 --- a/common/base/classes/base_form.php +++ b/common/base/classes/base_form.php @@ -103,8 +103,9 @@ class c_base_form_problem extends c_base_return_string { /** * Associations a field via the field name with this problem. * - * @param string $field_name + * @param string|null $field_name * The field name to assign. + * Set to NULL remove all field names (useful for errors that affect the entire form). * * @return c_base_return_status * TRUE on success, FALSE otherwise. @@ -113,6 +114,11 @@ class c_base_form_problem extends c_base_return_string { * @see: c_base_session::save() */ public function set_field($field_name) { + if (is_null($field_name)) { + $this->fields = array(); + return new c_base_return_true(); + } + if (!is_string($field_name) || empty($field_name)) { $error = c_base_error::s_log(NULL, array('arguments' => array(':argument_name' => 'field_name', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::INVALID_ARGUMENT); return c_base_return_error::s_false($error); diff --git a/common/base/classes/base_mime.php b/common/base/classes/base_mime.php index ad15919..4d44c95 100644 --- a/common/base/classes/base_mime.php +++ b/common/base/classes/base_mime.php @@ -25,7 +25,8 @@ class c_base_mime { const TYPE_UNKNOWN = 1; const TYPE_PROVIDED = 2; const TYPE_STREAM = 3; - const TYPE_FORM_DATA = 4; + const TYPE_DATA_FORM = 4; + const TYPE_DATA_URL = 5; const TYPE_TEXT = 1000; const TYPE_TEXT_PLAIN = 1001; @@ -96,7 +97,8 @@ class c_base_mime { private static $s_names_provided = array( self::TYPE_PROVIDED => array('*/*', 'text/*', 'image/*', 'audio/*', 'video/*', 'application/*'), self::TYPE_STREAM => array('application/octet-stream'), - self::TYPE_FORM_DATA => array('multipart/form-data'), + self::TYPE_DATA_FORM => array('multipart/form-data'), + self::TYPE_DATA_URL => array('application/x-www-form-urlencoded'), ); private static $s_names_text = array( diff --git a/common/base/classes/base_session.php b/common/base/classes/base_session.php index 93537b6..1bfb688 100644 --- a/common/base/classes/base_session.php +++ b/common/base/classes/base_session.php @@ -1036,7 +1036,13 @@ class c_base_session extends c_base_return { } $response = c_base_return_array::s_value_exact($response); - if (empty($response['result']) || !is_array($response['result'])) { + if (isset($response['error']) && isset($response['error']['message']) && is_string($response['error']['message'])) { + $error = c_base_error::s_log(' ' . $response['error']['message'], array('arguments' => array(':operation_name' => 'this->p_transfer', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::OPERATION_FAILURE); + unset($response); + + return c_base_return_error::s_false($error); + } + elseif (empty($response['result']) || !is_array($response['result'])) { unset($response); $error = c_base_error::s_log(NULL, array('arguments' => array(':operation_name' => 'this->p_transfer', ':function_name' => __CLASS__ . '->' . __FUNCTION__)), i_base_error_messages::OPERATION_FAILURE); diff --git a/database/sql/reservation/reservation-associations.sql b/database/sql/reservation/reservation-associations.sql index 2109ddb..de81074 100644 --- a/database/sql/reservation/reservation-associations.sql +++ b/database/sql/reservation/reservation-associations.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Associations **/ -/** This depends on: base-fields.sql **/ +/** This depends on: reservation-fields.sql **/ start transaction; @@ -19,7 +19,7 @@ create table s_tables.t_associations ( id_manager bigint not null, id_coordinator bigint not null, id_group bigint, - id_sort smallint not null default 0, + id_sort smallint default 0, name_machine varchar(128) not null, name_human varchar(256) not null, @@ -72,7 +72,7 @@ create view s_users.v_associations_self with (security_barrier=true) as with this_user as (select id from s_users.v_users_locked_not_self), allowed_groups as (select id from s_users.v_groups_self) select id, id_manager, id_coordinator, id_group, id_sort, name_machine, name_human, is_approved, is_cancelled, is_denied, is_troubled, is_locked, date_created, date_changed, date_synced, date_approved, date_cancelled, date_denied, date_troubled, date_locked, field_affiliation, field_classification from s_tables.t_associations - where is_deleted is not true and (id_manager in (select * from this_user) or id_group in (select * from allowed_groups)); + where not is_deleted and (id_manager in (select * from this_user) or id_group in (select * from allowed_groups)); grant select on s_users.v_associations_self to r_reservation_requester, r_reservation_reviewer; @@ -81,7 +81,7 @@ grant select on s_users.v_associations_self to r_reservation_requester, r_reserv create view s_users.v_associations_manage with (security_barrier=true) as with this_user as (select id from s_users.v_users_locked_not_self) select id, id_creator, id_coordinator, id_group, id_sort, name_machine, name_human, is_approved, is_cancelled, is_denied, is_troubled, is_locked, date_created, date_changed, date_synced, date_approved, date_cancelled, date_denied, date_troubled, date_locked, field_affiliation, field_classification from s_tables.t_associations - where is_deleted is not true and id_manager in (select * from this_user); + where not is_deleted and id_manager in (select * from this_user); grant select on s_users.v_associations_manage to r_reservation_requester, r_reservation_reviewer; @@ -90,7 +90,7 @@ grant select on s_users.v_associations_manage to r_reservation_requester, r_rese create view s_users.v_associations_coordinate with (security_barrier=true) as with this_user as (select id from s_users.v_users_locked_not_self) select id, id_creator, id_manager, id_group, id_sort, name_machine, name_human, is_approved, is_cancelled, is_denied, is_troubled, is_locked, date_created, date_changed, date_synced, date_approved, date_cancelled, date_denied, date_troubled, date_locked, field_affiliation, field_classification from s_tables.t_associations - where is_deleted is not true and id_coordinator in (select * from this_user); + where not is_deleted and id_coordinator in (select * from this_user); grant select on s_users.v_associations_coordinate to r_reservation_requester, r_reservation_reviewer; @@ -98,7 +98,7 @@ grant select on s_users.v_associations_coordinate to r_reservation_requester, r_ /** provide current user access to insert their own associations (with them as the manager) **/ create view s_users.v_associations_self_insert with (security_barrier=true) as select id_manager, id_group, id_coordinator, name_machine, name_human, field_affiliation, field_classification from s_tables.t_associations - where is_deleted is not true and id_manager in (select id from s_users.v_users_locked_not_self) + where not is_deleted and id_manager in (select id from s_users.v_users_locked_not_self) with check option; grant insert on s_users.v_associations_self_insert to r_reservation_requester, r_reservation_reviewer; @@ -107,7 +107,7 @@ grant insert on s_users.v_associations_self_insert to r_reservation_requester, r /** provide current user access to update associations they manager **/ create view s_users.v_associations_self_update with (security_barrier=true) as select id_manager, id_group, id_coordinator, name_machine, name_human, date_changed, field_affiliation, field_classification from s_tables.t_associations - where is_deleted is not true and id_manager in (select id from s_users.v_users_locked_not_self) + where not is_deleted and id_manager in (select id from s_users.v_users_locked_not_self) with check option; grant update on s_users.v_associations_self_update to r_reservation_requester, r_reservation_reviewer; diff --git a/database/sql/reservation/reservation-dates.sql b/database/sql/reservation/reservation-dates.sql index fe14fb5..102c042 100644 --- a/database/sql/reservation/reservation-dates.sql +++ b/database/sql/reservation/reservation-dates.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Dates **/ -/** This depends on: base-main.sql **/ +/** This depends on: reservation-main.sql **/ start transaction; @@ -41,15 +41,15 @@ grant select on s_tables.t_date_contexts to r_reservation_auditor; grant select,usage on s_tables.se_date_contexts_id to r_reservation_manager; create index i_date_contexts_deleted_not on s_tables.t_date_contexts (id) - where is_deleted is not true; + where not is_deleted; create index i_date_contexts_locked_not on s_tables.t_date_contexts (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create view s_requesters.v_date_contexts with (security_barrier=true) as select id, id_external, name_machine, name_human, is_locked from s_tables.t_date_contexts - where is_deleted is not true; + where not is_deleted; grant select on s_requesters.v_date_contexts to r_reservation_requester, r_reservation_reviewer; diff --git a/database/sql/reservation/reservation-fields.sql b/database/sql/reservation/reservation-fields.sql index 8bbef1b..a8ca736 100644 --- a/database/sql/reservation/reservation-fields.sql +++ b/database/sql/reservation/reservation-fields.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Fields **/ -/** This depends on: base-users.sql **/ +/** This depends on: reservation-users.sql **/ start transaction; @@ -41,14 +41,14 @@ grant select on s_tables.t_field_affiliations to r_reservation_auditor; grant select,usage on s_tables.se_field_affiliations_id to r_reservation_manager; create index i_field_affiliations_deleted_not on s_tables.t_field_affiliations (id) - where is_deleted is not true; + where not is_deleted; create index i_field_affiliations_locked_not on s_tables.t_field_affiliations (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create view s_users.v_field_affiliations with (security_barrier=true) as select id, id_external, name_machine, name_human, is_locked from s_tables.t_field_affiliations - where is_deleted is not true; + where not is_deleted; grant select on s_users.v_field_affiliations to r_reservation, r_reservation_system; @@ -89,15 +89,15 @@ grant select on s_tables.t_field_classifications to r_reservation_auditor; grant select,usage on s_tables.se_field_classifications_id to r_reservation_manager; create index i_field_classifications_deleted_not on s_tables.t_field_classifications (id) - where is_deleted is not true; + where not is_deleted; create index i_field_classifications_locked_not on s_tables.t_field_classifications (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create view s_users.v_field_classifications with (security_barrier=true) as select id, id_external, name_machine, name_human, is_locked from s_tables.t_field_classifications - where is_deleted is not true; + where not is_deleted; grant select on s_users.v_field_classifications to r_reservation, r_reservation_system; diff --git a/database/sql/reservation/reservation-files.sql b/database/sql/reservation/reservation-files.sql new file mode 100644 index 0000000..b3c8bbc --- /dev/null +++ b/database/sql/reservation/reservation-files.sql @@ -0,0 +1,95 @@ +/** Standardized SQL Structure - Files **/ +/** This depends on: reservation-users.sql, reservation-types.sql **/ +start transaction; + + + +/** Custom database specific settings (do this on every connection made) **/ +set bytea_output to hex; +set search_path to s_administers,s_managers,s_auditors,s_publishers,s_insurers,s_financers,s_reviewers,s_editors,s_drafters,s_requesters,s_users,public; +set datestyle to us; + + + +create table s_tables.t_files ( + id bigint not null, + id_creator bigint not null, + id_creator_session bigint not null, + id_type bigint not null, + id_group bigint, + + name_machine varchar(128) not null, + name_human varchar(256) not null, + + is_private boolean default true not null, + is_locked boolean default false not null, + is_deleted boolean default false not null, + is_system boolean default false not null, + is_user boolean default false not null, + + field_data bytea not null, + + date_created timestamp default localtimestamp not null, + date_changed timestamp default localtimestamp not null, + date_locked timestamp, + date_deleted timestamp, + + constraint cp_files primary key (id), + + constraint cu_files_name_machine unique (name_machine), + constraint cu_files_field_path unique (field_path), + + constraint cc_files_id check (id > 0), + + constraint cf_files_id_creator foreign key (id_creator) references s_tables.t_users (id) on delete cascade on update cascade, + constraint cf_files_id_creator_session foreign key (id_creator_session) references s_tables.t_users (id) on delete cascade on update cascade, + constraint cf_files_id_type foreign key (id_type) references s_tables.t_path_types (id) on delete restrict on update cascade, + constraint cf_files_id_group foreign key (id_group) references s_tables.t_groups (id) on delete restrict on update cascade +); + +create sequence s_tables.se_files_id owned by s_tables.t_files.id; +alter table s_tables.t_files alter column id set default nextval('s_tables.se_files_id'::regclass); + +grant select,insert,update on s_tables.t_path_types to r_reservation_administer; +grant select on s_tables.t_files to r_reservation_manager, r_reservation_auditor; +grant select,usage on s_tables.se_files_id to r_reservation_administer; +grant usage on s_tables.se_files_id to r_reservation, r_reservation_system; + +create index i_files_deleted_not on s_tables.t_files (id) + where not is_deleted; + +create index i_files_private_not on s_tables.t_files (id) + where not is_deleted and not is_private; + +create index i_files_locked_not on s_tables.t_files (id) + where not is_deleted and not is_locked; + +create index i_files_public on s_tables.t_files (id) + where not is_deleted and not is_locked and not is_private; + + +create view s_users.v_files with (security_barrier=true) as + with allowed_groups as (select id from s_users.v_groups_self) + select id, id_type, id_group, name_machine, name_human, is_private, date_created, date_changed from s_tables.t_files + where not is_deleted and (not is_locked or id_group in (select * from allowed_groups)) and (not is_private or (is_private and id_group in (select * from allowed_groups))); + +grant select on s_users.v_files to r_reservation, r_reservation_system; + +create view public.v_files with (security_barrier=true) as + select id, id_type, NULL::bigint as id_group, name_machine, name_human, NULL::bool as is_private, NULL::bool as date_created, NULL::bool as date_changed from s_tables.t_files + where not is_deleted and not is_locked and not is_private; + +grant select on public.v_path_types to r_reservation, r_public, r_reservation_system; + + +create trigger tr_files_date_changed_deleted_or_locked + before update on s_tables.t_files + for each row execute procedure s_administers.f_common_update_date_changed_deleted_or_locked(); + +create trigger tr_files_enforce_creator_and_session_ids + before insert on s_tables.t_files + for each row execute procedure s_administers.f_common_enforce_creator_and_session_ids(); + + + +commit transaction; diff --git a/database/sql/reservation/reservation-first.sql b/database/sql/reservation/reservation-first.sql index 437d780..5ab1e4d 100644 --- a/database/sql/reservation/reservation-first.sql +++ b/database/sql/reservation/reservation-first.sql @@ -22,6 +22,7 @@ create role r_reservation_system inherit nologin; create role r_reservation_revision_requests inherit nologin; create role r_reservation_statistics_update inherit nologin; create role r_reservation_logger inherit nologin; +create role r_reservation_groups_handler inherit nologin; grant r_reservation to r_reservation_administer with admin option; diff --git a/database/sql/reservation/reservation-groups.sql b/database/sql/reservation/reservation-groups.sql index 0ccb6a6..25d79ed 100644 --- a/database/sql/reservation/reservation-groups.sql +++ b/database/sql/reservation/reservation-groups.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Groups */ -/** This depends on: base-users.sql **/ +/** This depends on: reservation-users.sql **/ start transaction; @@ -25,7 +25,7 @@ create table s_tables.t_groups ( id_external bigint, id_manager bigint, - id_sort smallint not null default 0, + id_sort smallint default 0, name_machine varchar(128) not null, name_human varchar(256) not null, @@ -33,6 +33,7 @@ create table s_tables.t_groups ( is_locked boolean default false not null, is_deleted boolean default false not null, is_composite boolean default false not null, + is_user boolean default false not null, can_manage_paths boolean default false not null, @@ -58,10 +59,10 @@ create table s_tables.t_groups ( create sequence s_tables.se_groups_id owned by s_tables.t_groups.id; alter table s_tables.t_groups alter column id set default nextval('s_tables.se_groups_id'::regclass); -grant select,insert,update on s_tables.t_groups to r_reservation_manager; +grant select,insert,update on s_tables.t_groups to r_reservation_manager, r_reservation_groups_handler; grant select on s_tables.t_groups to r_reservation_auditor; grant select,usage on s_tables.se_groups_id to r_reservation_manager; -grant usage on s_tables.se_groups_id to r_reservation, r_reservation_system; +grant usage on s_tables.se_groups_id to r_reservation, r_reservation_system, r_reservation_groups_handler; /* Note: id_sort is only needed when directly validating against id or name_machine because both of those are already an index. */ create index i_groups_id_sort_a on s_tables.t_groups (id_sort) with (fillfactor = 100) where id_sort = 97; @@ -91,27 +92,65 @@ create index i_groups_id_sort_x on s_tables.t_groups (id_sort) with (fillfactor create index i_groups_id_sort_y on s_tables.t_groups (id_sort) with (fillfactor = 100) where id_sort = 121; create index i_groups_id_sort_z on s_tables.t_groups (id_sort) with (fillfactor = 100) where id_sort = 122; +/* only allow one user group per user. */ +create unique index i_groups_one_user_group on s_tables.t_groups (id_manager) where is_user; + /*** provide group managers access to manage their groups ***/ create view s_users.v_groups_manage_self with (security_barrier=true) as with this_user as (select id from s_users.v_users_locked_not_self) - select id, id_external, name_machine, name_human, is_locked, is_composite, can_manage_paths, settings from s_tables.t_groups - where is_deleted is not true and id_manager in (select * from this_user); + select id, id_external, name_machine, name_human, is_locked, is_composite, is_user, can_manage_paths, settings from s_tables.t_groups + where not is_deleted and id_manager in (select * from this_user); grant select on s_users.v_groups_manage_self to r_reservation, r_reservation_system; create view s_users.v_groups_manage_update with (security_barrier=true) as - select id, id_external, name_machine, name_human, is_locked, is_composite, can_manage_paths, settings from s_tables.t_groups - where is_deleted is not true and id_manager in (select id from s_users.v_users_locked_not_self) + select id, id_external, name_machine, name_human, is_locked, is_composite, is_user, can_manage_paths, settings from s_tables.t_groups + where not is_deleted and id_manager in (select id from s_users.v_users_locked_not_self) with check option; grant update on s_users.v_groups_manage_update to r_reservation, r_reservation_system; -create trigger tr_groups_date_changed_deleted_or_locked - before update on s_tables.t_groups - for each row execute procedure s_administers.f_common_update_date_changed_deleted_or_locked(); +/** each user shall have their own group. + Note: this violates the naming standard where group name should be first, such as 'group_kday' instead of 'kday_group'. + This is done specifically because of the id_sort index optimization. + name_machine is used instad of name_human for the group human name because name_machine is guaranteed to exist. +**/ +create function s_administers.f_groups_group_user_insert() returns trigger security definer as $$ + begin + insert into s_tables.t_groups (id_manager, name_machine, name_human, is_user) values (new.id, new.name_machine || '_user', 'User: ' || new.name_machine, true); + + return null; + end; +$$ language plpgsql; + +alter function s_administers.f_groups_group_user_insert () owner to r_reservation_groups_handler; + +create function s_administers.f_groups_group_user_update() returns trigger security definer as $$ + begin + if (old.name_machine <> new.name_machine) then + update s_tables.t_groups set name_machine = new.name_machine || '_user', name_human = 'User: ' || new.name_machine, is_locked = new.is_locked, is_deleted = new.is_deleted where id_manager = new.id and is_user; + elseif (old.is_deleted <> new.is_deleted) then + update s_tables.t_groups set is_locked = new.is_locked, is_deleted = new.is_deleted where id_manager = new.id and is_user; + elseif (old.is_locked <> new.is_locked) then + update s_tables.t_groups set is_locked = new.is_locked where id_manager = new.id and is_user; + end if; + + return null; + end; +$$ language plpgsql; + +alter function s_administers.f_groups_group_user_update () owner to r_reservation_groups_handler; + + +create trigger tr_groups_group_user_insert + after insert on s_tables.t_users + for each row execute procedure s_administers.f_groups_group_user_insert(); +create trigger tr_groups_group_user_update + after update on s_tables.t_users + for each row execute procedure s_administers.f_groups_group_user_update(); /** Groups to Users Association **/ @@ -140,31 +179,31 @@ grant select on s_tables.t_groups to r_reservation_auditor; /*** provide current user access to their own information ***/ create view s_users.v_groups_self with (security_barrier=true) as - with allowed_groups as (select id_group from s_tables.t_group_users where is_deleted is not true and is_locked is not true and id_user in (select id from s_users.v_users_locked_not_self)) + with allowed_groups as (select id_group from s_tables.t_group_users where not is_deleted and not is_locked and id_user in (select id from s_users.v_users_locked_not_self)) select id, id_external, id_manager, name_machine, name_human, is_locked, is_composite, date_created, date_changed, date_synced, can_manage_paths, settings from s_tables.t_groups - where is_deleted is not true and id in (select * from allowed_groups); + where not is_deleted and id in (select * from allowed_groups); grant select on s_users.v_groups_self to r_reservation, r_reservation_system; /*** provide group managers access to manage users assigned to their groups (any user id less than 1000 is reserved/special case, prohibit those). ***/ create view s_users.v_group_users_manage with (security_barrier=true) as - with managed_groups as (select id from s_tables.t_groups where is_deleted is not true and id_manager in (select id from s_users.v_users_locked_not_self)), - available_users as (select id from s_tables.t_users where is_deleted is not true and is_locked is not true and is_system is not true and is_public is not true) + with managed_groups as (select id from s_tables.t_groups where not is_deleted and id_manager in (select id from s_users.v_users_locked_not_self)), + available_users as (select id from s_tables.t_users where not is_deleted and not is_locked and not is_system and not is_public) select id_user, id_group, is_locked from s_tables.t_group_users - where is_deleted is not true and id_group in (select * from managed_groups) and id_user in (select * from available_users); + where not is_deleted and id_group in (select * from managed_groups) and id_user in (select * from available_users); grant select on s_users.v_group_users_manage to r_reservation, r_reservation_system; create view s_users.v_group_users_manage_insert with (security_barrier=true) as select id_user, id_group from s_tables.t_group_users - where is_deleted is not true and id_group in (select id from s_users.v_groups_manage_self) and id_group in (select id_group from s_tables.t_group_users where is_deleted is not true and is_locked is not true and id_user in (select id from s_users.v_users_locked_not_self)) and id_user in (select id from s_tables.t_users where is_deleted is not true and is_locked is not true and is_system is not true and is_public is not true) + where not is_deleted and id_group in (select id from s_users.v_groups_manage_self) and id_group in (select id_group from s_tables.t_group_users where not is_deleted and not is_locked and id_user in (select id from s_users.v_users_locked_not_self)) and id_user in (select id from s_tables.t_users where not is_deleted and not is_locked and not is_system and not is_public) with check option; grant insert on s_users.v_group_users_manage_insert to r_reservation, r_reservation_system; create view s_users.v_group_users_manage_update with (security_barrier=true) as select id_user, id_group from s_tables.t_group_users - where is_deleted is not true and id_group in (select id from s_users.v_groups_manage_self) and id_group in (select id_group from s_tables.t_group_users where is_deleted is not true and is_locked is not true and id_user in (select id from s_users.v_users_locked_not_self)) and id_user in (select id from s_tables.t_users where is_deleted is not true and is_locked is not true and is_system is not true and is_public is not true) + where not is_deleted and id_group in (select id from s_users.v_groups_manage_self) and id_group in (select id_group from s_tables.t_group_users where not is_deleted and not is_locked and id_user in (select id from s_users.v_users_locked_not_self)) and id_user in (select id from s_tables.t_users where not is_deleted and not is_locked and not is_system and not is_public) with check option; grant update on s_users.v_group_users_manage_update to r_reservation, r_reservation_system; @@ -201,23 +240,23 @@ grant select on s_tables.t_groups to r_reservation_auditor; /*** provide group managers access to manage composite groups. ***/ create view s_users.v_group_composites with (security_barrier=true) as - with allowed_groups as (select id from s_users.v_groups_self where is_locked is not true), - managed_groups as (select id from s_users.v_groups_manage_self where is_locked is not true) + with allowed_groups as (select id from s_users.v_groups_self where not is_locked), + managed_groups as (select id from s_users.v_groups_manage_self where not is_locked) select id_composite, id_group, is_locked from s_tables.t_group_composites - where is_deleted is not true and id_group in (select * from managed_groups) or id_group in (select * from allowed_groups); + where not is_deleted and id_group in (select * from managed_groups) or id_group in (select * from allowed_groups); grant select on s_users.v_group_composites to r_reservation, r_reservation_system; create view s_users.v_group_composites_manage_insert with (security_barrier=true) as select id_user, id_group from s_tables.t_group_users - where is_deleted is not true and id_group in (select id_group from s_users.v_group_users_manage where is_locked is not true) + where not is_deleted and id_group in (select id_group from s_users.v_group_users_manage where not is_locked) with check option; grant insert on s_users.v_group_composites_manage_insert to r_reservation, r_reservation_system; create view s_users.v_group_composites_manage_update with (security_barrier=true) as select id_user, id_group from s_tables.t_group_users - where is_deleted is not true and id_group in (select id_group from s_users.v_group_users_manage where is_locked is not true) + where not is_deleted and id_group in (select id_group from s_users.v_group_users_manage where not is_locked) with check option; grant update on s_users.v_group_composites_manage_update to r_reservation, r_reservation_system; diff --git a/database/sql/reservation/reservation-last.sql b/database/sql/reservation/reservation-last.sql index 2c219a3..ec489ea 100644 --- a/database/sql/reservation/reservation-last.sql +++ b/database/sql/reservation/reservation-last.sql @@ -77,90 +77,90 @@ insert into s_tables.t_path_types (id, name_machine, name_human) values (2, 'use /** create well known types that can then be user for indexes (all new types added should be considered for custom indexing). **/ -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (0, '0', 'Undefined'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (1, '1', 'Invalid'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (2, '2', 'Unknown'); - -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (100, '100', 'Continue'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (101, '101', 'Switching Protocols'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (102, '102', 'Processing'); - -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (200, '200', 'OK'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (201, '201', 'Created'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (202, '202', 'Accepted'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (203, '203', 'Non-Authoritative Information'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (204, '204', 'No Content'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (205, '205', 'Reset Content'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (206, '206', 'Partial Content'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (207, '207', 'Multi-Status'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (208, '208', 'Already Reported'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (226, '226', 'IM used'); - -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (300, '300', 'Multiple Choices'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (301, '301', 'Moved Permanently'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (302, '302', 'Found'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (303, '303', 'See Other'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (304, '304', 'Not Modified'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (305, '305', 'Use Proxy'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (306, '306', 'Switch Proxy'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (307, '307', 'Temporary Redirect'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (308, '308', 'Permanent Redirect'); - -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (400, '400', 'Bad Request'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (401, '401', 'Unauthorized'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (402, '402', 'Payment Required'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (403, '403', 'Forbidden'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (404, '404', 'Not Found'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (405, '405', 'Method Not Allowed'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (406, '406', 'Not Acceptable'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (407, '407', 'Proxy Authentication Required'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (408, '408', 'Request Timeout'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (409, '409', 'Conflict'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (410, '410', 'Gone'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (411, '411', 'Length Required'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (412, '412', 'Precondition Failed'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (413, '413', 'Payload Too Large'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (414, '414', 'Request-URI Too Long'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (415, '415', 'Unsupported Media Type'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (416, '416', 'Requested Range Not Satisfiable'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (417, '417', 'Expectation Failed'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (422, '422', 'Misdirected Request'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (423, '423', 'Locked'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (424, '424', 'Failed Dependency'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (426, '426', 'Upgrade Required'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (428, '428', 'Precondition Required'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (429, '429', 'Too Many Requests'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (431, '431', 'Request Header Fields Too Large'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (451, '451', 'Unavailable For Legal Reasons'); - -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (500, '500', 'Internal Server Error'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (501, '501', 'Not Implemented'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (502, '502', 'Bad Gateway'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (503, '503', 'Service Unavailable'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (504, '504', 'Gateway Timeout'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (505, '505', 'HTTP Version Not Supported'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (506, '506', 'Variant Also Negotiates'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (507, '507', 'Insufficient Storage'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (508, '508', 'Loop Detected'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (510, '510', 'Not Extended'); -insert into s_tables.t_log_http_status_codes (id, name_machine, name_human) values (511, '511', 'Network Authentication Required'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (0, '0', 'Undefined'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (1, '1', 'Invalid'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (2, '2', 'Unknown'); + +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (100, '100', 'Continue'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (101, '101', 'Switching Protocols'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (102, '102', 'Processing'); + +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (200, '200', 'OK'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (201, '201', 'Created'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (202, '202', 'Accepted'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (203, '203', 'Non-Authoritative Information'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (204, '204', 'No Content'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (205, '205', 'Reset Content'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (206, '206', 'Partial Content'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (207, '207', 'Multi-Status'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (208, '208', 'Already Reported'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (226, '226', 'IM used'); + +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (300, '300', 'Multiple Choices'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (301, '301', 'Moved Permanently'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (302, '302', 'Found'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (303, '303', 'See Other'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (304, '304', 'Not Modified'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (305, '305', 'Use Proxy'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (306, '306', 'Switch Proxy'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (307, '307', 'Temporary Redirect'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (308, '308', 'Permanent Redirect'); + +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (400, '400', 'Bad Request'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (401, '401', 'Unauthorized'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (402, '402', 'Payment Required'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (403, '403', 'Forbidden'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (404, '404', 'Not Found'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (405, '405', 'Method Not Allowed'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (406, '406', 'Not Acceptable'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (407, '407', 'Proxy Authentication Required'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (408, '408', 'Request Timeout'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (409, '409', 'Conflict'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (410, '410', 'Gone'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (411, '411', 'Length Required'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (412, '412', 'Precondition Failed'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (413, '413', 'Payload Too Large'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (414, '414', 'Request-URI Too Long'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (415, '415', 'Unsupported Media Type'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (416, '416', 'Requested Range Not Satisfiable'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (417, '417', 'Expectation Failed'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (422, '422', 'Misdirected Request'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (423, '423', 'Locked'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (424, '424', 'Failed Dependency'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (426, '426', 'Upgrade Required'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (428, '428', 'Precondition Required'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (429, '429', 'Too Many Requests'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (431, '431', 'Request Header Fields Too Large'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (451, '451', 'Unavailable For Legal Reasons'); + +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (500, '500', 'Internal Server Error'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (501, '501', 'Not Implemented'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (502, '502', 'Bad Gateway'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (503, '503', 'Service Unavailable'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (504, '504', 'Gateway Timeout'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (505, '505', 'HTTP Version Not Supported'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (506, '506', 'Variant Also Negotiates'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (507, '507', 'Insufficient Storage'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (508, '508', 'Loop Detected'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (510, '510', 'Not Extended'); +insert into s_tables.t_log_type_http_status_codes (id, name_machine, name_human) values (511, '511', 'Network Authentication Required'); /*** start the sequence count at 1000 to allow for < 1000 to be reserved for special uses ***/ -alter sequence s_tables.se_log_severity_levels_id start 1000; -alter sequence s_tables.se_log_severity_levels_id restart; +alter sequence s_tables.se_log_type_severity_levels_id start 1000; +alter sequence s_tables.se_log_type_severity_levels_id restart; /** create well known types that can then be user for indexes (all new types added should be considered for custom indexing). **/ -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (0, 'none', 'None'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (1, 'information', 'Information'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (2, 'notice', 'Notice'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (3, 'debug', 'Debug'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (4, 'warning', 'Warning'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (5, 'error', 'Error'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (6, 'alert', 'Alert'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (7, 'critical', 'Critical'); -insert into s_tables.t_log_severity_levels (id, name_machine, name_human) values (8, 'emergency', 'Emergency'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (0, 'none', 'None'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (1, 'information', 'Information'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (2, 'notice', 'Notice'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (3, 'debug', 'Debug'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (4, 'warning', 'Warning'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (5, 'error', 'Error'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (6, 'alert', 'Alert'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (7, 'critical', 'Critical'); +insert into s_tables.t_log_type_severity_levels (id, name_machine, name_human) values (8, 'emergency', 'Emergency'); @@ -188,6 +188,7 @@ insert into s_tables.t_types_mime_types (id, id_category, name_machine, name_hum insert into s_tables.t_types_mime_types (id, id_category, name_machine, name_human, field_extension, field_mime) values (2, 2, 'provided_application', 'Provided Application', NULL, 'application/*'); insert into s_tables.t_types_mime_types (id, id_category, name_machine, name_human, field_extension, field_mime) values (3, 3, 'stream', 'Stream', 'octect-stream', 'application/octect-stream'); insert into s_tables.t_types_mime_types (id, id_category, name_machine, name_human, field_extension, field_mime) values (4, 4, 'multipart', 'Form Data', 'form-data', 'multipart/form-data'); +insert into s_tables.t_types_mime_types (id, id_category, name_machine, name_human, field_extension, field_mime) values (5, 11, 'application', 'URL Data', 'x-www-form-urlencoded', 'application/x-www-form-urlencoded'); insert into s_tables.t_types_mime_types (id, id_category, name_machine, name_human, field_extension, field_mime) values (1000, 5, 'text', 'Text', NULL, 'text/*'); insert into s_tables.t_types_mime_types (id, id_category, name_machine, name_human, field_extension, field_mime) values (1001, 5, 'text_plain', 'Plain Text', 'txt', 'text/plain'); diff --git a/database/sql/reservation/reservation-legal.sql b/database/sql/reservation/reservation-legal.sql index 5a3fbfe..d445cf2 100644 --- a/database/sql/reservation/reservation-legal.sql +++ b/database/sql/reservation/reservation-legal.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Legal */ -/** This depends on: base-users.sql **/ +/** This depends on: reservation-users.sql **/ start transaction; @@ -41,15 +41,15 @@ grant select on s_tables.t_legal_types to r_reservation_auditor; grant select,usage on s_tables.se_legal_types_id to r_reservation_manager; create index i_legal_types_deleted_not on s_tables.t_legal_types (id) - where is_deleted is not true; + where not is_deleted; create index i_legal_type_locked_not on s_tables.t_legal_types (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create view s_users.v_legal_types with (security_barrier=true) as select id, id_external, name_machine, name_human, is_locked from s_tables.t_legal_types - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; grant select on s_users.v_legal_types to r_reservation_auditor, r_reservation_requester; @@ -96,14 +96,14 @@ grant select,usage on s_tables.se_signatures_id to r_reservation_manager; grant usage on s_tables.se_signatures_id to r_reservation, r_reservation_system; create index i_signatures_deleted_not on s_tables.t_signatures (id) - where is_deleted is not true; + where not is_deleted; /*** provide current user access to their own information ***/ create view s_users.v_signatures_self with (security_barrier=true) as with this_user as (select id from s_users.v_users_locked_not_self) select id, id_type, id_request, date_created, field_fingerprint, field_signature from s_tables.t_signatures - where is_deleted is not true and id_creator in (select * from this_user); + where not is_deleted and id_creator in (select * from this_user); grant select on s_users.v_signatures_self to r_reservation, r_reservation_system; @@ -111,7 +111,7 @@ grant select on s_users.v_signatures_self to r_reservation, r_reservation_system /** provide current user access to insert their own associations **/ create view s_users.v_signatures_self_insert with (security_barrier=true) as select id, id_type, id_creator, id_request, field_fingerprint, field_signature from s_tables.t_signatures - where is_deleted is not true and id_creator in (select id from s_users.v_users_locked_not_self) + where not is_deleted and id_creator in (select id from s_users.v_users_locked_not_self) with check option; grant insert on s_users.v_signatures_self_insert to r_reservation, r_reservation_system; diff --git a/database/sql/reservation/reservation-log_groups.sql b/database/sql/reservation/reservation-log_groups.sql index 647f2fe..ebbc222 100644 --- a/database/sql/reservation/reservation-log_groups.sql +++ b/database/sql/reservation/reservation-log_groups.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Logs - Groups */ -/** This depends on: base-groups.sql **/ +/** This depends on: reservation-groups.sql **/ start transaction; @@ -49,7 +49,7 @@ grant select on s_users.v_log_groups_self to r_reservation, r_reservation_system create view s_users.v_log_groups_self_insert with (security_barrier=true) as select id_group, log_type, log_details from s_tables.t_log_groups - where id_user in (select id from s_users.v_users_locked_not_self) and id_group in (select id from s_users.v_groups_self where is_locked is not true) + where id_user in (select id from s_users.v_users_locked_not_self) and id_group in (select id from s_users.v_groups_self where not is_locked) with check option; grant insert on s_users.v_log_groups_self_insert to r_reservation, r_reservation_system; @@ -95,7 +95,7 @@ grant usage on s_tables.se_log_group_users_id to r_reservation, r_reservation_sy /** only allow select and insert for users when user id is current user **/ create view s_users.v_log_group_users_self with (security_barrier=true) as with this_user as (select id from s_users.v_users_locked_not_self), - allowed_groups as (select id from s_users.v_groups_self where is_locked is not true) + allowed_groups as (select id from s_users.v_groups_self where not is_locked) select id, id_user, id_group, log_type, log_date from s_tables.t_log_group_users where id_user in (select * from this_user) or id_group in (select * from allowed_groups); @@ -103,7 +103,7 @@ grant select on s_users.v_log_group_users_self to r_reservation, r_reservation_s create view s_users.v_log_group_users_self_insert with (security_barrier=true) as select id_group, log_type from s_tables.t_log_group_users - where id_user in (select id from s_users.v_users_locked_not_self) and id_group in (select id from s_users.v_groups_self where is_locked is not true) + where id_user in (select id from s_users.v_users_locked_not_self) and id_group in (select id from s_users.v_groups_self where not is_locked) with check option; grant insert on s_users.v_log_group_users_self_insert to r_reservation, r_reservation_system; diff --git a/database/sql/reservation/reservation-log_problems.sql b/database/sql/reservation/reservation-log_problems.sql index 58e6867..545812e 100644 --- a/database/sql/reservation/reservation-log_problems.sql +++ b/database/sql/reservation/reservation-log_problems.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Logs - Problems */ -/** This depends on: base-users.sql **/ +/** This depends on: reservation-users.sql **/ /* The problem logs are intended for temporary reporting of problems and are meant to allow permanent deletion. */ start transaction; @@ -13,7 +13,6 @@ set datestyle to us; /** Provide a log of problems, which are defined by the software. **/ -/* @todo: shouldnt there be a problem type code? */ create table s_tables.t_log_problems ( id bigint not null, @@ -35,11 +34,9 @@ alter table s_tables.t_log_problems alter column id set default nextval('s_table grant select,insert,update,delete on s_tables.t_log_problems to r_reservation_manager; grant select on s_tables.t_log_problems to r_reservation_auditor; -grant select,usage on s_tables.se_log_problems_id to r_reservation_manager, r_reservation_auditor; +grant select,usage on s_tables.se_log_problems_id to r_reservation_manager; grant usage on s_tables.se_log_problems_id to r_reservation, r_reservation_system; -/* @todo: it seems the views for allowing users to insert/delete problems needs to be created. */ - /** Provide a log of problems, associated with a given user. **/ @@ -101,8 +98,6 @@ create function s_tables.f_log_problems_users_delete() returns trigger security end; $$ language plpgsql; -reset role; - alter function s_tables.f_log_problems_users_delete () owner to r_reservation_logger; create trigger tr_log_problems_users_delete @@ -114,4 +109,5 @@ create trigger tr_log_problems_enforce_user_and_session_ids for each row execute procedure s_administers.f_common_enforce_user_and_session_ids(); + commit transaction; diff --git a/database/sql/reservation/reservation-log_types.sql b/database/sql/reservation/reservation-log_types.sql index 906c1ed..737fb34 100644 --- a/database/sql/reservation/reservation-log_types.sql +++ b/database/sql/reservation/reservation-log_types.sql @@ -1,6 +1,5 @@ /** Standardized SQL Structure - Logs - Types */ -/** This depends on: base-users.sql **/ -/* @todo: consider prepending t_log_types_ to all tables (except t_log_types itself). */ +/** This depends on: reservation-users.sql **/ start transaction; @@ -41,14 +40,14 @@ grant select on s_tables.t_log_types to r_reservation_manager, r_reservation_aud grant select,usage on s_tables.se_log_types_id to r_reservation_administer; create index i_log_types_deleted_not on s_tables.t_log_types (id) - where is_deleted is not true; + where not is_deleted; create index i_log_types_public on s_tables.t_log_types (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create view public.v_log_types with (security_barrier=true) as select id, name_machine, name_human from s_tables.t_log_types - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; grant select on public.v_log_types to r_reservation, r_public, r_reservation_system; @@ -60,7 +59,7 @@ create trigger tr_log_types_date_changed_deleted_or_locked /*** provide HTTP status codes ***/ -create table s_tables.t_log_http_status_codes ( +create table s_tables.t_log_type_http_status_codes ( id smallint not null, name_machine varchar(128) not null, @@ -74,34 +73,34 @@ create table s_tables.t_log_http_status_codes ( date_locked timestamp, date_deleted timestamp, - constraint cp_log_http_status_codes primary key (id), + constraint cp_log_type_http_status_codes primary key (id), - constraint cu_log_http_status_codes_user unique (name_machine), + constraint cu_log_type_http_status_codes_user unique (name_machine), - constraint cc_log_http_status_codes_id check (id >= 0 and id < 600) + constraint cc_log_type_http_status_codes_id check (id >= 0 and id < 600) ); -create sequence s_tables.se_log_http_status_codes_id owned by s_tables.t_log_http_status_codes.id; -alter table s_tables.t_log_http_status_codes alter column id set default nextval('s_tables.se_log_http_status_codes_id'::regclass); +create sequence s_tables.se_log_type_http_status_codes_id owned by s_tables.t_log_type_http_status_codes.id; +alter table s_tables.t_log_type_http_status_codes alter column id set default nextval('s_tables.se_log_type_http_status_codes_id'::regclass); -grant select,insert,update on s_tables.t_log_http_status_codes to r_reservation_administer; -grant select on s_tables.t_log_http_status_codes to r_reservation_manager, r_reservation_auditor; -grant select,usage on s_tables.se_log_http_status_codes_id to r_reservation_administer; +grant select,insert,update on s_tables.t_log_type_http_status_codes to r_reservation_administer; +grant select on s_tables.t_log_type_http_status_codes to r_reservation_manager, r_reservation_auditor; +grant select,usage on s_tables.se_log_type_http_status_codes_id to r_reservation_administer; -create view public.v_log_http_status_codes with (security_barrier=true) as - select id, name_machine, name_human from s_tables.t_log_http_status_codes; +create view public.v_log_type_http_status_codes with (security_barrier=true) as + select id, name_machine, name_human from s_tables.t_log_type_http_status_codes; -grant select on public.v_log_http_status_codes to r_reservation, r_public, r_reservation_system; +grant select on public.v_log_type_http_status_codes to r_reservation, r_public, r_reservation_system; -create trigger tr_log_http_status_codes_date_changed_deleted_or_locked - before update on s_tables.t_log_http_status_codes +create trigger tr_log_type_http_status_codes_date_changed_deleted_or_locked + before update on s_tables.t_log_type_http_status_codes for each row execute procedure s_administers.f_common_update_date_changed_deleted_or_locked(); /*** provide log severity level id and names ***/ -create table s_tables.t_log_severity_levels ( +create table s_tables.t_log_type_severity_levels ( id bigint not null, name_machine varchar(128) not null, name_human varchar(256) not null, @@ -114,29 +113,29 @@ create table s_tables.t_log_severity_levels ( date_locked timestamp, date_deleted timestamp, - constraint cp_log_severity_levels primary key (id), + constraint cp_log_type_severity_levels primary key (id), - constraint cu_log_severity_levels_user unique (name_machine), + constraint cu_log_type_severity_levels_user unique (name_machine), - constraint cc_log_severity_levels_id check (id >= 0) + constraint cc_log_type_severity_levels_id check (id >= 0) ); -create sequence s_tables.se_log_severity_levels_id owned by s_tables.t_log_severity_levels.id; -alter table s_tables.t_log_severity_levels alter column id set default nextval('s_tables.se_log_severity_levels_id'::regclass); +create sequence s_tables.se_log_type_severity_levels_id owned by s_tables.t_log_type_severity_levels.id; +alter table s_tables.t_log_type_severity_levels alter column id set default nextval('s_tables.se_log_type_severity_levels_id'::regclass); -grant select,insert,update on s_tables.t_log_severity_levels to r_reservation_administer; -grant select on s_tables.t_log_severity_levels to r_reservation_manager, r_reservation_auditor; -grant select,usage on s_tables.se_log_severity_levels_id to r_reservation_administer; +grant select,insert,update on s_tables.t_log_type_severity_levels to r_reservation_administer; +grant select on s_tables.t_log_type_severity_levels to r_reservation_manager, r_reservation_auditor; +grant select,usage on s_tables.se_log_type_severity_levels_id to r_reservation_administer; -create view s_users.v_log_severity_levels with (security_barrier=true) as - select id, name_machine, name_human from s_tables.t_log_severity_levels - where is_deleted is not true; +create view s_users.v_log_type_severity_levels with (security_barrier=true) as + select id, name_machine, name_human from s_tables.t_log_type_severity_levels + where not is_deleted; -grant select on s_users.v_log_severity_levels to r_reservation, r_public, r_reservation_system; +grant select on s_users.v_log_type_severity_levels to r_reservation, r_public, r_reservation_system; -create trigger tr_log_severity_levels_date_changed_deleted_or_locked - before update on s_tables.t_log_severity_levels +create trigger tr_log_type_severity_levels_date_changed_deleted_or_locked + before update on s_tables.t_log_type_severity_levels for each row execute procedure s_administers.f_common_update_date_changed_deleted_or_locked(); diff --git a/database/sql/reservation/reservation-log_users.sql b/database/sql/reservation/reservation-log_users.sql index 4976034..f2061da 100644 --- a/database/sql/reservation/reservation-log_users.sql +++ b/database/sql/reservation/reservation-log_users.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Logs */ -/** This depends on: base-users.sql **/ +/** This depends on: reservation-users.sql **/ start transaction; @@ -34,8 +34,8 @@ create table s_tables.t_log_users ( constraint cf_log_users_id_user foreign key (id_user) references s_tables.t_users (id) on delete restrict on update cascade, constraint cf_log_users_id_user_session foreign key (id_user_session) references s_tables.t_users (id) on delete restrict on update cascade, constraint cf_log_users_log_type foreign key (log_type) references s_tables.t_log_types (id) on delete restrict on update cascade, - constraint cf_log_users_log_severity foreign key (log_severity) references s_tables.t_log_severity_levels (id) on delete restrict on update cascade, - constraint cf_log_users_response_code foreign key (response_code) references s_tables.t_log_http_status_codes (id) on delete restrict on update cascade + constraint cf_log_users_log_severity foreign key (log_severity) references s_tables.t_log_type_severity_levels (id) on delete restrict on update cascade, + constraint cf_log_users_response_code foreign key (response_code) references s_tables.t_log_type_http_status_codes (id) on delete restrict on update cascade ); create sequence s_tables.se_log_users_id owned by s_tables.t_log_users.id; @@ -131,10 +131,10 @@ create view s_users.v_log_users_self_insert with (security_barrier=true) as grant insert on s_users.v_log_users_self_insert to r_reservation, r_reservation_system; -/** only allow insert for the public user **/ +/** public users should be able to insert, but should never be able to view the logs that they insert. **/ create view public.v_log_users_self_insert with (security_barrier=true) as select log_title, log_type, log_severity, log_details, request_client, response_code from s_tables.t_log_users - where id_user = 1 + where 'r_public' in (select pr.rolname from pg_auth_members pam inner join pg_roles pr on (pam.roleid = pr.oid) inner join pg_roles pr_u on (pam.member = pr_u.oid) where pr_u.rolname = current_user and pr.rolname = 'r_public') with check option; grant insert on public.v_log_users_self_insert to r_public; @@ -167,7 +167,7 @@ create table s_tables.t_log_user_activity ( constraint cf_log_user_activity_id_user foreign key (id_user) references s_tables.t_users (id) on delete restrict on update cascade, constraint cf_log_user_activity_id_user_session foreign key (id_user_session) references s_tables.t_users (id) on delete restrict on update cascade, - constraint cf_log_user_activity_response_code foreign key (response_code) references s_tables.t_log_http_status_codes (id) on delete restrict on update cascade + constraint cf_log_user_activity_response_code foreign key (response_code) references s_tables.t_log_type_http_status_codes (id) on delete restrict on update cascade ); create sequence s_tables.se_log_user_activity_id owned by s_tables.t_log_user_activity.id; @@ -219,10 +219,10 @@ create view s_users.v_log_user_activity_self_insert with (security_barrier=true) grant insert on s_users.v_log_user_activity_self_insert to r_reservation, r_reservation_system; -/** only allow insert for the public user **/ +/** public users should be able to insert, but should never be able to view the logs that they insert. **/ create view public.v_log_user_activity_self_insert with (security_barrier=true) as select request_path, request_arguments, request_client, request_headers, response_headers, response_code from s_tables.t_log_user_activity - where id_user = 1 + where id_user in (select id from public.v_users_locked_not_self) with check option; grant insert on public.v_log_user_activity_self_insert to r_public; diff --git a/database/sql/reservation/reservation-main.sql b/database/sql/reservation/reservation-main.sql index 850f256..e42827e 100644 --- a/database/sql/reservation/reservation-main.sql +++ b/database/sql/reservation/reservation-main.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Main */ -/** This depends on: base-first.sql **/ +/** This depends on: reservation-first.sql **/ /* @todo: add restrictions to even managers and administers so that ALL users access via views to allow for disabling any account (even an admin). only the postgresql/root account may access tables directly. This requires changing permissions and adding the appropriate s_administers and s_managers tables. @@ -41,7 +41,7 @@ grant usage on schema s_drafters to r_reservation_drafter; grant usage on schema s_requesters to r_reservation_requester; grant usage on schema s_users to r_reservation; -grant usage on schema s_tables to r_reservation_revision_requests, r_reservation_statistics_update, r_reservation_logger; +grant usage on schema s_tables to r_reservation_revision_requests, r_reservation_statistics_update, r_reservation_logger, r_reservation_groups_handler; /** Composite Types **/ @@ -176,16 +176,16 @@ create type public.ct_field_insurance as ( /* User ID and Session User ID Functions */ create function s_administers.f_common_enforce_user_and_session_ids() returns trigger as $$ begin - new.id_user = coalesce((select id from v_users_self), 1); - new.id_user_session = coalesce((select id from v_users_self_session), 1); + new.id_user = (select id from v_users_self); + new.id_user_session = (select id from v_users_self_session); return new; end; $$ language plpgsql; create function s_administers.f_common_enforce_creator_and_session_ids() returns trigger as $$ begin - new.id_creator = coalesce((select id from v_users_self), 1); - new.id_creator_session = coalesce((select id from v_users_self_session), 1); + new.id_creator = (select id from v_users_self); + new.id_creator_session = (select id from v_users_self_session); return new; end; $$ language plpgsql; diff --git a/database/sql/reservation/reservation-paths.sql b/database/sql/reservation/reservation-paths.sql index da9e6b2..8537cfc 100644 --- a/database/sql/reservation/reservation-paths.sql +++ b/database/sql/reservation/reservation-paths.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Content **/ -/** This depends on: base-groups.sql **/ +/** This depends on: reservation-groups.sql **/ start transaction; @@ -41,22 +41,22 @@ grant select on s_tables.t_path_types to r_reservation_manager, r_reservation_au grant select,usage on s_tables.se_path_types_id to r_reservation_administer; create index i_path_types_deleted_not on s_tables.t_path_types (id) - where is_deleted is not true; + where not is_deleted; create index i_path_types_public on s_tables.t_path_types (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create view s_managers.v_path_types with (security_barrier=true) as select id, name_machine, name_human, is_locked, date_created, date_changed from s_tables.t_path_types - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; grant select on s_managers.v_path_types to r_reservation_manager; create view public.v_path_types with (security_barrier=true) as select id, name_machine, name_human, FALSE as is_locked, NULL::timestamp as date_created, NULL::timestamp as date_changed from s_tables.t_path_types - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; grant select on public.v_path_types to r_reservation, r_public, r_reservation_system; @@ -113,28 +113,28 @@ grant select,usage on s_tables.se_paths_id to r_reservation_administer; grant usage on s_tables.se_paths_id to r_reservation, r_reservation_system; create index i_paths_deleted_not on s_tables.t_paths (id) - where is_deleted is not true; + where not is_deleted; create index i_paths_private_not on s_tables.t_paths (id) - where is_deleted is not true and is_private is not true; + where not is_deleted and not is_private; create index i_paths_locked_not on s_tables.t_paths (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create index i_paths_public on s_tables.t_paths (id) - where is_deleted is not true and is_locked is not true and is_private is not true; + where not is_deleted and not is_locked and not is_private; create view s_users.v_paths with (security_barrier=true) as with allowed_groups as (select id from s_users.v_groups_self) select id, id_type, id_group, name_machine, name_human, is_private, date_created, date_changed from s_tables.t_paths - where is_deleted is not true and (is_locked is not true or id_group in (select * from allowed_groups)) and (is_private is not true or (is_private is true and id_group in (select * from allowed_groups))); + where not is_deleted and (not is_locked or id_group in (select * from allowed_groups)) and (not is_private or (is_private and id_group in (select * from allowed_groups))); grant select on s_users.v_paths to r_reservation, r_reservation_system; create view public.v_paths with (security_barrier=true) as select id, id_type, NULL::bigint as id_group, name_machine, name_human, NULL::bool as is_private, NULL::bool as date_created, NULL::bool as date_changed from s_tables.t_paths - where is_deleted is not true and is_locked is not true and is_private is not true; + where not is_deleted and not is_locked and not is_private; grant select on public.v_path_types to r_reservation, r_public, r_reservation_system; diff --git a/database/sql/reservation/reservation-requests.sql b/database/sql/reservation/reservation-requests.sql index 59f4b9d..00b8cb7 100644 --- a/database/sql/reservation/reservation-requests.sql +++ b/database/sql/reservation/reservation-requests.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Requests **/ -/** This depends on: base-fields.sql, base-workflow.sql **/ +/** This depends on: reservation-fields.sql, base-workflow.sql **/ start transaction; @@ -41,15 +41,15 @@ grant select on s_tables.t_request_types to r_reservation_auditor; grant select,usage on s_tables.se_request_types_id to r_reservation_manager; create index i_request_types_deleted_not on s_tables.t_request_types (id) - where is_deleted is not true; + where not is_deleted; create index i_request_types_public on s_tables.t_request_types (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create view s_requesters.v_request_types with (security_barrier=true) as select id, id_external, name_machine, name_human from s_tables.t_request_types - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; grant select on s_requesters.v_request_types to r_reservation_auditor, r_reservation_requester; @@ -147,7 +147,7 @@ create table s_tables.t_requests ( constraint cc_requests_id check (id > 0), constraint cc_requests_id_revision check (id_revision > -1), - constraint cc_requests_approved check ((is_approved is true and is_denied is not true) or (is_approved is not true and is_denied is true)), + constraint cc_requests_approved check ((is_approved and not is_denied) or (not is_approved and is_denied)), constraint cf_requests_id_creator foreign key (id_creator) references s_tables.t_users (id) on delete restrict on update cascade, constraint cf_requests_id_creator_session foreign key (id_creator_session) references s_tables.t_users (id) on delete restrict on update cascade, @@ -164,28 +164,28 @@ grant select,usage on s_tables.se_requests_id to r_reservation_manager; grant usage on s_tables.se_requests_id to r_reservation, r_reservation_system; create index i_requests_deleted_not on s_tables.t_requests (id) - where is_deleted is not true; + where not is_deleted; create index i_requests_locked_not on s_tables.t_requests (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create index i_requests_approved on s_tables.t_requests (id) - where is_deleted is not true and is_cancelled is not true and is_approved is true; + where not is_deleted and not is_cancelled and is_approved; create index i_requests_approved_cancelled on s_tables.t_requests (id) - where is_deleted is not true and is_cancelled is true and is_approved is true; + where not is_deleted and is_cancelled and is_approved; create index i_requests_denied on s_tables.t_requests (id) - where is_deleted is not true and is_cancelled is not true and is_denied is true; + where not is_deleted and not is_cancelled and is_denied; create index i_requests_troubled on s_tables.t_requests (id) - where is_deleted is not true and is_cancelled is not true and is_troubled is true; + where not is_deleted and not is_cancelled and is_troubled; create index i_requests_cancelled on s_tables.t_requests (id) - where is_deleted is not true and is_cancelled is true; + where not is_deleted and is_cancelled; create index i_requests_locked on s_tables.t_requests (id) - where is_deleted is not true and is_locked is true; + where not is_deleted and is_locked; /*** approved requests (but not cancelled) ***/ @@ -197,7 +197,7 @@ create view s_users.v_requests_approved with (security_barrier=true) as field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and is_cancelled is not true and is_approved is true; + where not is_deleted and not is_cancelled and is_approved; grant select on s_users.v_requests_approved to r_reservation, r_reservation_system; @@ -211,7 +211,7 @@ create view s_users.v_requests_approved_cancelled with (security_barrier=true) a field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and is_cancelled is true and is_approved is true; + where not is_deleted and is_cancelled and is_approved; grant select on s_users.v_requests_approved_cancelled to r_reservation, r_reservation_system; @@ -225,7 +225,7 @@ create view s_users.v_requests_denied with (security_barrier=true) as field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and is_cancelled is not true and is_denied is true; + where not is_deleted and not is_cancelled and is_denied; grant select on s_users.v_requests_denied to r_reservation, r_reservation_system; @@ -239,7 +239,7 @@ create view s_users.v_requests_troubled with (security_barrier=true) as field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and is_cancelled is not true and is_troubled is true; + where not is_deleted and not is_cancelled and is_troubled; grant select on s_users.v_requests_troubled to r_reservation, r_reservation_system; @@ -253,7 +253,7 @@ create view s_users.v_requests_cancelled with (security_barrier=true) as field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and is_cancelled is true; + where not is_deleted and is_cancelled; grant select on s_users.v_requests_cancelled to r_reservation, r_reservation_system; @@ -268,7 +268,7 @@ create view s_users.v_requests_self with (security_barrier=true) as field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and id_association in (select id from associations); + where not is_deleted and id_association in (select id from associations); grant select on s_users.v_requests_self to r_reservation, r_reservation_system; @@ -283,7 +283,7 @@ create view s_users.v_requests_manage with (security_barrier=true) as field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and id_association in (select id from associations); + where not is_deleted and id_association in (select id from associations); grant select on s_users.v_requests_self to r_reservation, r_reservation_system; @@ -298,7 +298,7 @@ create view s_users.v_requests_coordinate with (security_barrier=true) as field_additional, field_dates, field_fees_custodial, field_fees_equipment, field_fees_facilities, field_fees_grounds, field_fees_maintenance, field_fees_other, field_fees_security, field_fees_university, field_location, field_information_attendance, field_information_organization, field_information_adviser_approval, field_insurance_affiliated, field_insurance_contractor, field_insurance_unaffiliated, field_plans_activities, field_plans_audience, field_plans_description, field_presentation_designing_material, field_presentation_external_audio_person, field_presentation_production, field_presentation_printed_material, field_presentation_publicity, field_presentation_technical_equipment, field_presentation_university_logo, field_registration_revenue, field_registration_phone, field_registration_required, field_registration_ticket_dates, field_registration_ticket_phone, field_registration_ticket_price, field_registration_ticket_website, field_registration_website, field_setup_other_tables, field_setup_parking_assistance, field_setup_podium, field_setup_portable_stage, field_setup_rectangular_tables_8ft, field_setup_road_closures, field_setup_round_tables_8ft, field_setup_security, field_setup_special_requests, field_setup_standard_blue_chairs, field_services_alcohol_served, field_services_food, field_services_open_flames, field_title, in_state, in_step from s_tables.t_requests - where is_deleted is not true and id_association in (select id from associations); + where not is_deleted and id_association in (select id from associations); grant select on s_users.v_requests_self to r_reservation, r_reservation_system; @@ -384,7 +384,7 @@ create table s_tables.t_request_revisions_original ( constraint cp_request_revisions_original primary key (id_request), - constraint cc_request_revisions_original_approved check ((is_approved is true and is_denied is not true) or (is_approved is not true and is_denied is true)), + constraint cc_request_revisions_original_approved check ((is_approved and not is_denied) or (not is_approved and is_denied)), constraint cf_request_revisions_original_id_request foreign key (id_request) references s_tables.t_requests (id) on delete restrict on update cascade, constraint cf_request_revisions_original_request_type foreign key (id_type) references s_tables.t_request_types (id) on delete restrict on update cascade, @@ -501,7 +501,7 @@ create table s_tables.t_request_revisions ( constraint cp_request_revisions primary key (id_request, id_revision), constraint cc_request_revisions_id_request check (id_request > 0), - constraint cc_request_revisions_approved check ((is_approved is true and is_denied is not true) or (is_approved is not true and is_denied is true)), + constraint cc_request_revisions_approved check ((is_approved and not is_denied) or (not is_approved and is_denied)), constraint cf_request_revisions_id_request foreign key (id_request) references s_tables.t_requests (id) on delete restrict on update cascade, constraint cf_request_revisions_request_type foreign key (id_type) references s_tables.t_request_types (id) on delete restrict on update cascade, diff --git a/database/sql/reservation/reservation-statistics.sql b/database/sql/reservation/reservation-statistics.sql index f9a8451..d5d9306 100644 --- a/database/sql/reservation/reservation-statistics.sql +++ b/database/sql/reservation/reservation-statistics.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Statistics **/ -/** This depends on: base-log_users.sql **/ +/** This depends on: reservation-log_users.sql **/ start transaction; @@ -26,7 +26,7 @@ create table s_tables.t_statistics_http_status_codes ( constraint cc_statistics_http_status_codes_count check (count >= 0), - constraint cf_statistics_http_status_codes_code foreign key (code) references s_tables.t_log_http_status_codes (id) on delete restrict on update cascade + constraint cf_statistics_http_status_codes_code foreign key (code) references s_tables.t_log_type_http_status_codes (id) on delete restrict on update cascade ); grant select,insert,update on s_tables.t_statistics_http_status_codes to r_reservation_manager, r_reservation_statistics_update; diff --git a/database/sql/reservation/reservation-types.sql b/database/sql/reservation/reservation-types.sql index 6b2bd71..1ae0d8c 100644 --- a/database/sql/reservation/reservation-types.sql +++ b/database/sql/reservation/reservation-types.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Logs - Types */ -/** This depends on: base-main.sql **/ +/** This depends on: reservation-main.sql **/ start transaction; @@ -39,7 +39,7 @@ grant select,insert,update on s_tables.t_types_mime_categorys to r_reservation_a create view public.v_types_mime_categorys with (security_barrier=true) as select id, name_machine, name_human, is_locked from s_tables.t_types_mime_categorys - where is_deleted is not true; + where not is_deleted; grant select on public.v_types_mime_categorys to r_reservation, r_public, r_reservation_system; @@ -48,7 +48,7 @@ grant select,insert,update on s_tables.t_types_mime_categorys to r_reservation_a create view public.v_types_mime_categorys_locked_not with (security_barrier=true) as select id, name_machine, name_human, field_category from s_tables.t_types_mime_categorys - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; grant select on public.v_types_mime_categorys_locked_not to r_reservation, r_public, r_reservation_system; @@ -89,13 +89,13 @@ grant select,insert,update on s_tables.t_types_mime_types to r_reservation_admin create view public.v_types_mime_types with (security_barrier=true) as select id, id_category, name_machine, name_human, field_extension, field_mime, is_locked from s_tables.t_types_mime_types - where is_deleted is not true; + where not is_deleted; grant select on public.v_types_mime_types to r_reservation, r_public, r_reservation_system; create view public.v_types_mime_types_locked_not with (security_barrier=true) as select id, id_category, name_machine, name_human, field_extension, field_mime, is_locked from s_tables.t_types_mime_types - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; grant select on public.v_types_mime_types to r_reservation, r_public, r_reservation_system; diff --git a/database/sql/reservation/reservation-users.sql b/database/sql/reservation/reservation-users.sql index 2d1264e..32ece05 100644 --- a/database/sql/reservation/reservation-users.sql +++ b/database/sql/reservation/reservation-users.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Users */ -/** This depends on: base-main.sql **/ +/** This depends on: reservation-main.sql **/ start transaction; @@ -16,7 +16,7 @@ create table s_tables.t_users ( id bigint not null, id_external bigint, - id_sort smallint not null default 0, + id_sort smallint default 0, name_machine varchar(128) not null, name_human public.ct_name_person default (null, null, null, null, null, null) not null, @@ -67,16 +67,16 @@ grant select,usage on s_tables.se_users_id to r_reservation_administer; grant usage on s_tables.se_users_id to r_reservation, r_reservation_system; create index i_users_deleted_not on s_tables.t_users (id) - where is_deleted is not true; + where not is_deleted; create index i_users_private_not on s_tables.t_users (id) - where is_deleted is not true and is_private is not true; + where not is_deleted and not is_private; create index i_users_locked_not on s_tables.t_users (id) - where is_deleted is not true and is_locked is not true; + where not is_deleted and not is_locked; create index i_users_private_email_not on s_tables.t_users (id) - where is_deleted is not true and is_private is not true and (address_email).private is not true; + where not is_deleted and not is_private and not (address_email).private; /* Note: id_sort is only needed when directly validating against id or name_machine because both of those are already an index. */ @@ -112,39 +112,53 @@ create index i_users_id_sort_z on s_tables.t_users (id_sort) with (fillfactor = /*** provide current user access to their own information (system users are not allowed to update their account) ***/ create view s_users.v_users_self with (security_barrier=true) as select id, id_external, id_sort, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, can_manage_roles, date_created, date_changed, date_synced, date_locked, settings from s_tables.t_users - where is_deleted is not true and (name_machine)::text = (current_user)::text; + where not is_deleted and (name_machine)::text = (current_user)::text; grant select on s_users.v_users_self to r_reservation, r_reservation_system; create view s_users.v_users_self_session with (security_barrier=true) as select id, id_external, id_sort, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, can_manage_roles, date_created, date_changed, date_synced, date_locked, settings from s_tables.t_users - where is_deleted is not true and (name_machine)::text = (session_user)::text; + where not is_deleted and (name_machine)::text = (session_user)::text; grant select on s_users.v_users_self_session to r_reservation, r_reservation_system; +create view public.v_users_self_session with (security_barrier=true) as + with postgres_roles as (select pr.rolname from pg_auth_members pam inner join pg_roles pr on (pam.roleid = pr.oid) inner join pg_roles pr_u on (pam.member = pr_u.oid) where pr_u.rolname = current_user and pr.rolname = 'r_public') + select id, id_external, id_sort, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, can_manage_roles, date_created, date_changed, date_synced, date_locked, settings from s_tables.t_users + where not is_deleted and (name_machine)::text = (session_user)::text and 'r_public' in (select * from postgres_roles); + +grant select on public.v_users_self_session to r_public; + create view s_users.v_users_locked_not_self with (security_barrier=true) as select id, id_external, id_sort, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, can_manage_roles, date_created, date_changed, date_synced, date_locked, settings from s_tables.t_users - where is_deleted is not true and is_locked is not true and (name_machine)::text = (current_user)::text; + where not is_deleted and not is_locked and (name_machine)::text = (current_user)::text; grant select on s_users.v_users_locked_not_self to r_reservation, r_reservation_system; +create view public.v_users_locked_not_self with (security_barrier=true) as + with postgres_roles as (select pr.rolname from pg_auth_members pam inner join pg_roles pr on (pam.roleid = pr.oid) inner join pg_roles pr_u on (pam.member = pr_u.oid) where pr_u.rolname = current_user and pr.rolname = 'r_public') + select id, id_external, id_sort, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, can_manage_roles, date_created, date_changed, date_synced, date_locked, settings from s_tables.t_users + where not is_deleted and not is_locked and (name_machine)::text = (current_user)::text and 'r_public' in (select * from postgres_roles); + +grant select on public.v_users_locked_not_self to r_public; + create view s_users.v_users_can_manage_roles with (security_barrier=true) as - with this_user_can_manage_roles as (select id from s_users.v_users_locked_not_self where can_manage_roles is true) + with this_user_can_manage_roles as (select id from s_users.v_users_locked_not_self where can_manage_roles) select id_sort, name_human, address_email from s_tables.t_users - where is_deleted is not true and is_locked is not true and is_system is not true and is_public is not true and (name_machine)::text = (current_user)::text and id in (select * from this_user_can_manage_roles); + where not is_deleted and not is_locked and not is_system and not is_public and (name_machine)::text = (current_user)::text and id in (select * from this_user_can_manage_roles); grant select on s_users.v_users_can_manage_roles to r_reservation, r_reservation_system; create view s_users.v_users_self_insert with (security_barrier=true) as select id_external, name_human, address_email, is_private, settings from s_tables.t_users - where is_deleted is not true and is_locked is not true and is_system is not true and is_public is not true and (name_machine)::text = (current_user)::text + where not is_deleted and not is_locked and not is_system and not is_public and (name_machine)::text = (current_user)::text with check option; grant insert on s_users.v_users_self_insert to r_reservation, r_reservation_system; create view s_users.v_users_self_update with (security_barrier=true) as select address_email, is_private, settings from s_tables.t_users - where is_deleted is not true and is_locked is not true and is_system is not true and is_public is not true and (name_machine)::text = (current_user)::text + where not is_deleted and not is_locked and not is_system and not is_public and (name_machine)::text = (current_user)::text with check option; grant update on s_users.v_users_self_update to r_reservation, r_reservation_system; @@ -153,7 +167,7 @@ grant update on s_users.v_users_self_update to r_reservation, r_reservation_syst /**** anonymous user has uid = 1 ****/ create view public.v_users_self with (security_barrier=true) as select id, id_external, id_sort, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, date_created, date_changed, date_synced, date_locked, settings from s_tables.t_users - where is_deleted is not true and id = 1; + where not is_deleted and id = 1; grant select on public.v_users_self to r_public, r_reservation, r_reservation_system; @@ -161,7 +175,7 @@ grant select on public.v_users_self to r_public, r_reservation, r_reservation_sy /*** provide public user information ***/ create view public.v_users with (security_barrier=true) as select id, null::bigint as id_external, id_sort, name_machine, name_human, null::public.ct_email as address_email, null::bool as is_administer, null::bool as is_manager, null::bool as is_auditor, null::bool as is_publisher, null::bool as is_insurer, null::bool as is_financer, null::bool as is_reviewer, null::bool as is_editor, null::bool as is_drafter, null::bool as is_requester, is_system, is_public, null::bool as is_locked, null::bool as is_private, null::bool as can_manage_roles, null::timestamp as date_created, null::timestamp as date_changed, null::timestamp as date_synced, null::timestamp as date_locked, null::json as settings from s_tables.t_users - where (is_deleted is not true and is_private is not true) or (is_deleted is not true and (name_machine)::text = (current_user)::text); + where (not is_deleted and not is_private) or (not is_deleted and (name_machine)::text = (current_user)::text); grant select on public.v_users to r_reservation, r_public, r_reservation_system; @@ -169,7 +183,7 @@ grant select on public.v_users to r_reservation, r_public, r_reservation_system; /*** provide e-mail address as public information only if it is explicitly allowed ***/ create view public.v_users_email with (security_barrier=true) as select id, null::bigint as id_external, id_sort, name_machine, name_human, address_email, null::bool as is_administer, null::bool as is_manager, null::bool as is_auditor, null::bool as is_publisher, null::bool as is_insurer, null::bool as is_financer, null::bool as is_reviewer, null::bool as is_editor, null::bool as is_drafter, null::bool as is_requester, is_system, is_public, null::bool as is_locked, null::bool as is_private, null::bool as can_manage_roles, null::timestamp as date_created, null::timestamp as date_changed, null::timestamp as date_synced, null::timestamp as date_locked, null::json as settings from s_tables.t_users - where (is_deleted is not true and is_private is not true and (address_email).private is not true) or (is_deleted is not true and (name_machine)::text = (current_user)::text); + where (not is_deleted and not is_private and not (address_email).private) or (not is_deleted and (name_machine)::text = (current_user)::text); grant select on public.v_users_email to r_reservation, r_public, r_reservation_system; @@ -177,7 +191,7 @@ grant select on public.v_users_email to r_reservation, r_public, r_reservation_s /*** provide managers with the ability to modify accounts ***/ create view s_managers.v_users with (security_barrier=true) as select * from s_tables.t_users - where is_deleted is not true; + where not is_deleted; grant select on s_managers.v_users to r_reservation_manager; @@ -189,14 +203,14 @@ grant insert on s_managers.v_users_insert to r_reservation_manager; create view s_managers.v_users_update with (security_barrier=true) as select id, id_external, name_machine, name_human, address_email, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_locked, is_private, can_manage_roles, settings from s_tables.t_users - where is_deleted is not true + where not is_deleted with check option; grant update on s_managers.v_users_update to r_reservation_manager; create view s_managers.v_users_deleted with (security_barrier=true) as select id, id_external, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_insurer, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_locked, is_private, can_manage_roles, date_created, date_changed, date_synced, date_locked, settings from s_tables.t_users - where is_deleted is true; + where is_deleted; grant select on s_managers.v_users to r_reservation_manager; @@ -255,7 +269,7 @@ grant select on s_administers.m_users_date_created_previous_year to r_reservatio create function s_administers.f_users_insert_actions() returns trigger as $$ begin - if (new.name_machine = null) then + if (new.name_machine is null) then new.name_machine = current_user; end if; diff --git a/database/sql/reservation/reservation-workflow.sql b/database/sql/reservation/reservation-workflow.sql index c39b66f..00ac7cc 100644 --- a/database/sql/reservation/reservation-workflow.sql +++ b/database/sql/reservation/reservation-workflow.sql @@ -1,5 +1,5 @@ /** Standardized SQL Structure - Workflow **/ -/** This depends on: base-users.sql **/ +/** This depends on: reservation-users.sql **/ start transaction; diff --git a/examples/test.php b/examples/test.php index 08bb633..669566e 100755 --- a/examples/test.php +++ b/examples/test.php @@ -75,6 +75,20 @@ if (isset($stuff['cookie_login']['cookie'])) { $stuff['cookie_login']['cookie']->do_push(); } + + // additional cookies to expire. + if (isset($stuff['cookie_expire']['cookies']) && is_array($stuff['cookie_expire']['cookies'])) { + foreach ($stuff['cookie_expire']['cookies'] as $cookie) { + if (!($cookie instanceof c_base_cookie)) { + continue; + } + + $cookie->set_expires(-1); + $cookie->set_max_age(-1); + $cookie->do_push(); + } + unset($cookie); + } } function theme($stuff) { @@ -276,13 +290,14 @@ $name = $session->get_name()->get_value(); $password = $session->get_password()->get_value(); - assign_database_string($database, $name, $password, $session); + assign_database_string($database, $name, $password); unset($name); unset($password); $connected = connect_database($database); if ($connected) { set_log_user($database, 'logout'); + set_log_activity($database, 200); $database->do_disconnect(); } unset($connected); @@ -316,7 +331,7 @@ if ($result instanceof c_base_return_true) { $name = $session->get_name()->get_value(); $password = $session->get_password()->get_value(); - assign_database_string($database, $name, $password, $session); + assign_database_string($database, $name, $password); unset($name); unset($password); @@ -353,9 +368,10 @@ $stuff['login'] = ''; } - $user_data = get_user_data($database, $session->get_name()->get_value_exact()); + $user_data = get_user_data($database, $stuff, $session->get_name()->get_value_exact()); - $stuff['login'] .= ' - You are logged in as: ' . $session->get_name()->get_value_exact() . '
' . "\n"; + $stuff['login'] .= ' - You are logged in as: ' . $user_data['name_machine'] . '
' . "\n"; + $stuff['login'] .= ' - Your session user is: ' . $session->get_name()->get_value_exact() . '
' . "\n"; #$stuff['login'] .= ' - Your password is: ' . $session->get_password()->get_value_exact() . '
' . "\n"; $stuff['login'] .= ' - You will be auto-logged out at: ' . $data['expire'] . '
' . "\n"; $stuff['login'] .= '
' . "\n"; @@ -364,20 +380,29 @@ $stuff['login'] .= '
' . "\n"; $logged_in = TRUE; + if (!isset($user_data['name_machine']) || $user_data['name_machine'] != $session->get_name()->get_value_exact()) { + $stuff['login'] .= 'Your session name does not match the logged in name.' . '
' . "\n"; + $stuff['login'] .= 'This can happen when the user name has been deleted from the database for an existing session.' . '
' . "\n"; + $stuff['login'] .= 'Your session cookie is being deleted.' . '
' . "\n"; + $stuff['login'] .= '
' . "\n"; + + $cookie->set_expires(-1); + $cookie->set_max_age(-1); + $stuff['cookie_login']['cookie'] = $cookie; + } + ldap($stuff, $session->get_name()->get_value_exact()); set_log_activity($database); - get_database_data($database, $stuff); + if (!empty($session->get_name()->get_value_exact()) && $session->get_name()->get_value_exact() != 'u_public') { + get_database_data($database, $stuff); - if (!empty($session->get_name()->get_value_exact())) { $log = get_log_activity($database); $table = build_log_activity_table($log); $stuff['login'] .= "
" . $table . "
"; unset($log); unset($table); - } - if (!empty($session->get_name()->get_value_exact())) { $log = get_log_users($database); $table = build_log_users_table($log); $stuff['login'] .= "
" . $table . "
"; @@ -413,30 +438,49 @@ $session->set_host($remote_address); $session->set_password($_POST['login_password']); + $is_public = FALSE; $user_data = array(); - $account_exists = check_login_access($stuff, $database, $_POST['login_name'], $_POST['login_password'], $session); + + // allow direct login as u_public and assume/require that the u_public account already exists. + if ($_POST['login_name'] == 'u_public') { + $is_public = TRUE; + $account_exists = FALSE; + } + else { + $account_exists = check_login_access($stuff, $database, $_POST['login_name'], $_POST['login_password'], $session); + } + if (!$account_exists) { - $user_id = 1; $session->set_name('u_public'); $session->set_password(NULL); - if (!isset($stuff['login'])) { - $stuff['login'] = ''; + + if ($is_public === FALSE) { + if (!isset($stuff['login'])) { + $stuff['login'] = ''; + } + $stuff['login'] .= "DEBUG: user " . htmlspecialchars($_POST['login_name'], ENT_HTML5 | ENT_NOQUOTES | ENT_DISALLOWED | ENT_SUBSTITUTE, 'UTF-8') . " does not exist and user does not exist in ldap (falling back to the public account to access the database).
"; } - $stuff['login'] .= "DEBUG: does not exist and does not exist in ldap (falling back to the public account to access the database).
"; - $database->set_session($session); #$database->set_persistent(TRUE); - assign_database_string($database, 'u_public', NULL, $session); + assign_database_string($database, 'u_public', NULL); $connected = connect_database($database); - if ($connected) { - set_log_user($database, 'login_failure', $_POST['login_name'], NULL, 401); - set_log_activity($database, 401); + if ($is_public === FALSE) { + set_log_user($database, 'login_failure', $_POST['login_name'], NULL, 401); + set_log_activity($database, 401); + } + else { + set_log_user($database, 'login'); + set_log_activity($database, 200); + } + + $user_data = get_user_data($database, $stuff, 'u_public'); $stuff['login'] .= ' - Accessing database as: u_public' . '
' . "\n"; - $stuff['login'] .= ' - Your user id is: 1 ' . '
' . "\n"; + $stuff['login'] .= ' - Your user id is: ' . (isset($user_data['id']) ? $user_data['id'] : 'does not exist') . '
' . "\n"; $stuff['login'] .= '
' . "\n"; $logged_in = TRUE; + $is_public = TRUE; } } else { @@ -451,13 +495,12 @@ } $connected = TRUE; - $stuff['login'] .= "DEBUG: account already exists or exists in ldap.
"; - $user_data = get_user_data($database, $_POST['login_name'], $ldap_data); - $user_id = $user_data['id_user']; - unset($user_data['id_user']); + $stuff['login'] .= "DEBUG: account already exists.
"; + $user_data = get_user_data($database, $stuff, $_POST['login_name'], $ldap_data); unset($ldap_data); } - $session->set_id_user($user_id); + unset($account_exists); + $session->set_settings($user_data); if (!$connected) { @@ -469,30 +512,46 @@ } if (!$failure) { - $result = $session->do_push(600, 1800); // (10 minutes, 30 minutes) - $session->do_disconnect(); + if (!$is_public) { + $result = $session->do_push(600, 1800); // (10 minutes, 30 minutes) + $session_expire = $session->get_timeout_expire()->get_value_exact(); + $session_max = $session->get_timeout_max()->get_value_exact(); + $expire_string = date("D, d M Y H:i:s T", $session_expire); - set_log_user($database, 'login', NULL, $session->get_timeout_expire()->get_value_exact()); + $cookie->set_expires($session_expire); + $cookie->set_max_age(NULL); - $session_expire = $session->get_timeout_expire()->get_value_exact(); - $session_max = $session->get_timeout_max()->get_value_exact(); - $expire_string = date("D, d M Y H:i:s T", $session_expire); - $cookie->set_expires($session_expire); - $cookie->set_max_age(NULL); + set_log_user($database, 'login', NULL, $session_expire); + set_log_activity($database, 200); - if ($result instanceof c_base_return_true) { - $data = array( - 'session_id' => $session->get_session_id()->get_value_exact(), - 'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unnecessary, but provided for debug purposes. - ); - $cookie->set_value($data); - $stuff['cookie_login']['cookie'] = $cookie; + if ($result instanceof c_base_return_true) { + $data = array( + 'session_id' => $session->get_session_id()->get_value_exact(), + 'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unnecessary, but provided for debug purposes. + ); + $cookie->set_value($data); + $stuff['cookie_login']['cookie'] = $cookie; + } + } + else { + $session_expire = NULL; + $session_max = NULL; + $expire_string = 'indefinite'; + + $cookie->set_expires(-1); + $cookie->set_max_age(-1); + $result = new c_base_return_true(); + } + $session->do_disconnect(); + + if ($result instanceof c_base_return_true) { if (!isset($stuff['login'])) { $stuff['login'] = ''; } - $stuff['login'] .= ' - You are logged in as: ' . $session->get_name()->get_value_exact() . '
' . "\n"; + $stuff['login'] .= ' - You are logged in as: ' . $user_data['name_machine'] . '
' . "\n"; + $stuff['login'] .= ' - Your session user is: ' . $session->get_name()->get_value_exact() . '
' . "\n"; #$stuff['login'] .= ' - Your password is: ' . $session->get_password()->get_value_exact() . '
' . "\n"; $stuff['login'] .= ' - You will be auto-logged out at: ' . $expire_string . ' (' . $session_expire . ')' . '
' . "\n"; $stuff['login'] .= '
' . "\n"; @@ -506,18 +565,16 @@ } set_log_activity($database); - get_database_data($database, $stuff); + if (!empty($session->get_name()->get_value_exact()) && $session->get_name()->get_value_exact() != 'u_public') { + get_database_data($database, $stuff); - if (!empty($session->get_name()->get_value_exact())) { $log = get_log_activity($database); $table = build_log_activity_table($log); $stuff['login'] .= "
" . $table . "
"; unset($log); unset($table); - } - if (!empty($session->get_name()->get_value_exact())) { $log = get_log_users($database); $table = build_log_users_table($log); $stuff['login'] .= "
" . $table . "
"; @@ -533,13 +590,31 @@ $stuff['login'] = ''; } - $error = $session->get_error(); - $stuff['login'] .= ' - failed to save requested session, error: ' . print_r($error, TRUE) . "
"; - unset($error); + $error_messages = ''; + $errors = $result->get_error(); + if (is_array($errors)) { + foreach ($errors as $error) { + if (!($error instanceof c_base_error)) { + continue; + } + + $error_message = $error->get_message(); + if (!is_string($error_message)) { + $error_message = NULL; + } + + $error_messages .= $stuff['error_messages']::s_render_error_message($error, TRUE, FALSE, $error_message)->get_value_exact(); + unset($error_message); + } + unset($error); + } + unset($errors); + + $stuff['login'] .= ' - failed to save requested session, error: ' . $error_messages . "
"; + unset($error_messages); } } - unset($user_id); unset($session); } } @@ -579,8 +654,8 @@ } function get_database_data(&$database, &$stuff) { - $stuff['login'] .= 'query: "select * from v_users where is_system is not true and is_public is not true limit 20;"
' . "\n"; - $query_result = $database->do_query(' where is_system is not true and is_public is not true limit 20'); + $stuff['login'] .= 'query: "select * from v_users where not is_system and not is_public limit 20;"
' . "\n"; + $query_result = $database->do_query(' where not is_system and not is_public limit 20'); if ($query_result instanceof c_base_database_result) { $all = $query_result->fetch_all(); $stuff['login'] .= "
    "; @@ -593,8 +668,8 @@ unset($column); unset($value); } + unset($all); unset($row); - unset($row_number); } else { if (!isset($stuff['errors'])) { @@ -612,8 +687,11 @@ function check_login_access(&$stuff, &$database, $username, $password, $session) { if ($username == 'u_public') return FALSE; - $database->set_session($session); - assign_database_string($database, $username, $password, $session); + if ($database->is_connected() instanceof c_base_return_true) { + return TRUE; + } + + assign_database_string($database, $username, $password); $connected = connect_database($database); if ($connected) { @@ -638,21 +716,20 @@ } unset($errors); } - unset($ensure_result); - - // try again now that the system has attempted to ensure the user account exists. - $connected = connect_database($database); - if ($connected) { - set_log_user($database, 'create_user'); - return TRUE; + else { + // try again now that the system has attempted to ensure the user account exists. + $connected = connect_database($database); + if ($connected) { + set_log_user($database, 'create_user'); + return TRUE; + } } + unset($ensure_result); return FALSE; } - function assign_database_string(&$database, $username, $password, $session) { - $database->set_session($session); - + function assign_database_string(&$database, $username, $password) { $connection_string = new c_base_connection_string(); $connection_string->set_host('127.0.0.1'); $connection_string->set_port(5432); @@ -791,31 +868,87 @@ return TRUE; } - function get_user_data(&$database, $user_name, $ldap_data = NULL) { - $user_data = array( - 'id_user' => NULL, - ); - $query_result = $database->do_query('select id, id_external, name_human, address_email, is_private, is_locked, is_system, is_public, date_created, date_changed, settings from v_users_self'); + function get_user_data(&$database, &$stuff, $user_name, $ldap_data = NULL) { + $user_data = array(); + $query_result = $database->do_query('select id, id_external, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, date_created, date_changed, date_synced, date_locked, settings from v_users_self'); + + + if (c_base_return::s_has_error($query_result)) { + $errors = $query_result->get_error(); + if (is_array($errors)) { + if (!isset($stuff['errors'])) { + $stuff['errors'] = ''; + } + + foreach ($errors as $error) { + if ($error instanceof c_base_error) { + $stuff['errors'] .= '
  1. ' . $stuff['error_messages']::s_render_error_message($error)->get_value_exact() . '
  2. '; + } + } + unset($error); + } + unset($errors); + } + if ($query_result instanceof c_base_database_result) { if ($query_result->number_of_rows()->get_value_exact() > 0) { $result = $query_result->fetch_row(); + + if (c_base_return::s_has_error($result)) { + $errors = $result->get_error(); + if (is_array($errors)) { + if (!isset($stuff['errors'])) { + $stuff['errors'] = ''; + } + + foreach ($errors as $error) { + if ($error instanceof c_base_error) { + $stuff['errors'] .= '
  3. ' . $stuff['error_messages']::s_render_error_message($error)->get_value_exact() . '
  4. '; + } + } + unset($error); + } + unset($errors); + } + if (!($result instanceof c_base_return_false)) { $result_array = $result->get_value(); if (!empty($result_array)) { - $user_data['id_user'] = $result_array[0]; + $user_data['id'] = $result_array[0]; $user_data['id_external'] = $result_array[1]; - $user_data['name_human'] = $result_array[2]; - $user_data['address_email'] = $result_array[3]; - $user_data['is_private'] = $result_array[4]; - $user_data['is_locked'] = $result_array[5]; - $user_data['is_system'] = $result_array[6]; - $user_data['is_public'] = $result_array[7]; - $user_data['date_created'] = $result_array[8]; - $user_data['date_changed'] = $result_array[9]; - $user_data['settings'] = json_decode($result_array[10], TRUE); + $user_data['name_machine'] = $result_array[2]; + $user_data['name_human'] = $result_array[3]; + $user_data['address_email'] = $result_array[4]; + $user_data['is_administer'] = $result_array[5]; + $user_data['is_manager'] = $result_array[6]; + $user_data['is_auditor'] = $result_array[7]; + $user_data['is_publisher'] = $result_array[8]; + $user_data['is_financer'] = $result_array[9]; + $user_data['is_reviewer'] = $result_array[10]; + $user_data['is_editor'] = $result_array[11]; + $user_data['is_drafter'] = $result_array[12]; + $user_data['is_requester'] = $result_array[13]; + $user_data['is_system'] = $result_array[14]; + $user_data['is_public'] = $result_array[15]; + $user_data['is_locked'] = $result_array[16]; + $user_data['is_private'] = $result_array[17]; + $user_data['date_created'] = $result_array[18]; + $user_data['date_changed'] = $result_array[19]; + $user_data['date_synced'] = $result_array[20]; + $user_data['date_locked'] = $result_array[21]; + $user_data['settings'] = json_decode($result_array[22], TRUE); } } } + + if (!isset($user_data['id'])) { + // note: the error here is not recored because the user account may not exist yet and needs to be auto-created. + #if (!isset($stuff['errors'])) { + # $stuff['errors'] = ''; + #} + + #$stuff['errors'] .= '
  5. No valid data found for the user: ' . $user_name . '
  6. '; + } } else { if (!isset($stuff['errors'])) { @@ -823,10 +956,13 @@ } $stuff['errors'] .= '
  7. ' . htmlspecialchars($database->get_last_error()->get_value_exact(), ENT_HTML5 | ENT_NOQUOTES | ENT_DISALLOWED | ENT_SUBSTITUTE, 'UTF-8') . '
  8. '; + + return $user_data; } unset($query_result); - if (is_null($user_data['id_user'])) { + // if the user does not yet exist in the database (and is not the public user), then create it. + if (!isset($user_data['id']) && $user_name != 'u_public') { if (is_null($ldap_data)) { $query_result = $database->do_query('insert into v_users_self_insert (name_human.first, name_human.last, name_human.complete, address_email, id_external) values (null, null, null, null, null)'); if ($query_result instanceof c_base_return_false) { @@ -835,6 +971,10 @@ } $stuff['errors'] .= '
  9. ' . htmlspecialchars($database->get_last_error()->get_value_exact(), ENT_HTML5 | ENT_NOQUOTES | ENT_DISALLOWED | ENT_SUBSTITUTE, 'UTF-8') . '
  10. '; + + // don't attempt to perform select again because the insert query has failed and so there should be nothing to select. + unset($query_result); + return $user_data; } unset($query_result); } @@ -856,30 +996,54 @@ } $stuff['errors'] .= '
  11. ' . htmlspecialchars($database->get_last_error()->get_value_exact(), ENT_HTML5 | ENT_NOQUOTES | ENT_DISALLOWED | ENT_SUBSTITUTE, 'UTF-8') . '
  12. '; + + // don't attempt to perform select again because the insert query has failed and so there should be nothing to select. + unset($query_result); + return $user_data; } unset($query_result); } - $user_data['id_user'] = NULL; - $query_result = $database->do_query('select id, id_external, name_human, address_email, is_private, is_locked, is_system, is_public, date_created, date_changed, settings from v_users_self'); + $user_data['id'] = NULL; + $query_result = $database->do_query('select id, id_external, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, date_created, date_changed, date_synced, date_locked, settings from v_users_self'); if ($query_result instanceof c_base_database_result) { if ($query_result->number_of_rows()->get_value_exact() > 0) { $result = $query_result->fetch_row(); if (!($result instanceof c_base_return_false)) { $result_array = $result->get_value(); - $user_data['id_user'] = $result_array[0]; + $user_data['id'] = $result_array[0]; $user_data['id_external'] = $result_array[1]; - $user_data['name_human'] = $result_array[2]; - $user_data['address_email'] = $result_array[3]; - $user_data['is_private'] = $result_array[4]; - $user_data['is_locked'] = $result_array[5]; - $user_data['is_system'] = $result_array[6]; - $user_data['is_public'] = $result_array[7]; - $user_data['date_created'] = $result_array[8]; - $user_data['date_changed'] = $result_array[9]; - $user_data['settings'] = json_decode($result_array[10], TRUE); + $user_data['name_machine'] = $result_array[2]; + $user_data['name_human'] = $result_array[3]; + $user_data['address_email'] = $result_array[4]; + $user_data['is_administer'] = $result_array[5]; + $user_data['is_manager'] = $result_array[6]; + $user_data['is_auditor'] = $result_array[7]; + $user_data['is_publisher'] = $result_array[8]; + $user_data['is_financer'] = $result_array[9]; + $user_data['is_reviewer'] = $result_array[10]; + $user_data['is_editor'] = $result_array[11]; + $user_data['is_drafter'] = $result_array[12]; + $user_data['is_requester'] = $result_array[13]; + $user_data['is_system'] = $result_array[14]; + $user_data['is_public'] = $result_array[15]; + $user_data['is_locked'] = $result_array[16]; + $user_data['is_private'] = $result_array[17]; + $user_data['date_created'] = $result_array[18]; + $user_data['date_changed'] = $result_array[19]; + $user_data['date_synced'] = $result_array[20]; + $user_data['date_locked'] = $result_array[21]; + $user_data['settings'] = json_decode($result_array[22], TRUE); } } + + if (!isset($user_data['id'])) { + if (!isset($stuff['errors'])) { + $stuff['errors'] = ''; + } + + $stuff['errors'] .= '
  13. No valid data found for the user: ' . $user_name . '
  14. '; + } } else { if (!isset($stuff['errors'])) { @@ -897,7 +1061,6 @@ function get_log_activity(&$database) { $values = array(); - $user_id = NULL; $query_result = $database->do_query('select id, request_path, request_date, request_client, response_code from v_log_user_activity_self order by request_date desc limit 20;'); if ($query_result instanceof c_base_database_result) { $total_rows = $query_result->number_of_rows()->get_value_exact(); @@ -926,7 +1089,6 @@ function get_log_users(&$database) { $values = array(); - $user_id = NULL; $query_result = $database->do_query('select id, log_title, log_type, log_date, request_client, response_code from v_log_users_self order by log_date desc limit 10;'); if ($query_result instanceof c_base_database_result) { $total_rows = $query_result->number_of_rows()->get_value_exact(); diff --git a/program/reservation/index.php b/program/reservation/index.php index 3b2f000..d27fee6 100644 --- a/program/reservation/index.php +++ b/program/reservation/index.php @@ -256,20 +256,20 @@ if (empty($session->get_session_id()->get_value_exact())) { // check to see if user has filled out the login form. if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['form_id']) && $_POST['form_id'] == 'login_form') { - $problems = reservation_attempt_login($database, $settings, $session); + $logged_in = reservation_attempt_login($database, $settings, $session); - if ($problems instanceof c_base_return_false) { + if ($logged_in instanceof c_base_return_true) { reservation_build_page_dashboard($html, $settings, $session); // @todo: process and handle different paths here and load page as requested. } else { // store the problems in the session object (because session as a subclass of c_base_return). - $session->set_problems($problems->get_value_exact()); + $session->set_problems($logged_in->get_value_exact()); // @todo: render login failure. reservation_process_path_public($html, $settings, $session); } - unset($problems); + unset($logged_in); } else { reservation_process_path_public($html, $settings, $session); diff --git a/program/reservation/reservation_database.php b/program/reservation/reservation_database.php index 249f4e4..69b4aa6 100644 --- a/program/reservation/reservation_database.php +++ b/program/reservation/reservation_database.php @@ -114,100 +114,155 @@ return c_base_return_error::s_false($error); } - $id_sort = (int) ord($user_name[0]); - - $user_data = array( - 'id_user' => NULL, - 'id_sort' => $id_sort, - ); - $parameters = array( $id_sort, $user_name, ); - $query_result = $database->do_query('select id, id_sort, id_external, name_human, address_email, is_private, is_locked, date_created, date_changed, settings from v_users_self where id_sort = $1 and name_machine like $2', $parameters); + $query_result = $database->do_query('select id, id_sort, id_external, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, date_created, date_changed, date_synced, date_locked, settings from v_users_self where id_sort = $1 and name_machine = $2', $parameters); unset($parameters); - if ($query_result instanceof c_base_database_result) { - if ($query_result->number_of_rows()->get_value_exact() > 0) { - $result = $query_result->fetch_row(); - if (!($result instanceof c_base_return_false)) { - $result_array = $result->get_value(); - if (is_array($result_array) && !empty($result_array)) { - $user_data['id_user'] = $result_array[0]; - $user_data['id_sort'] = $result_array[1]; - $user_data['id_external'] = $result_array[2]; - $user_data['name_human'] = $result_array[3]; - $user_data['address_email'] = $result_array[4]; - $user_data['is_private'] = $result_array[5]; - $user_data['is_locked'] = $result_array[6]; - $user_data['date_created'] = $result_array[7]; - $user_data['date_changed'] = $result_array[8]; - $user_data['settings'] = json_decode($result_array[9], TRUE); - } - } - } + if (c_base_return::s_has_error($query_result)) { + return reservation_error_get_query('database->do_query(select from v_users_self)', __FUNCTION__, $query_result); } - unset($query_result); - if (is_null($user_data['id_user'])) { - if (is_null($ldap_data)) { - $parameters = array( - $id_sort, - ); + if ($query_result instanceof c_base_database_result && $query_result->number_of_rows()->get_value_exact() > 0) { + $result = $query_result->fetch_row(); + unset($query_result); - $query_result = $database->do_query('insert into v_users_self_insert (id_sort, name_machine) values ($1, user)', $parameters); - unset($query_result); - unset($parameters); + if (c_base_return::s_has_error($result)) { + return reservation_error_get_query('database->do_query(select from v_users_self)', __FUNCTION__, $result); } - else { - $email = explode('@', $ldap_data['mail']); - $parameters = array( - $ldap_data['givenname'], - $ldap_data['sn'], - $ldap_data['cn'], - $email[0], - $email[1], - $ldap_data['employeenumber'], - ); - $query_result = $database->do_query('insert into v_users_self_insert (id_sort, name_machine, name_human.first, name_human.last, name_human.complete, address_email, id_external) values (' . $id_sort . ', user, $1, $2, $3, ($4, $5, TRUE), $6)', $parameters); - unset($query_result); + + $result_array = $result->get_value(); + unset($result); + + if (is_array($result_array) && !empty($result_array)) { + $result_array = $result->get_value(); + + $user_data = array(); + $user_data['id'] = $result_array[0]; + $user_data['id_sort'] = $result_array[1]; + $user_data['id_external'] = $result_array[2]; + $user_data['name_machine'] = $result_array[3]; + $user_data['name_human'] = $result_array[4]; + $user_data['address_email'] = $result_array[5]; + $user_data['is_administer'] = $result_array[6]; + $user_data['is_manager'] = $result_array[7]; + $user_data['is_auditor'] = $result_array[8]; + $user_data['is_publisher'] = $result_array[9]; + $user_data['is_financer'] = $result_array[10]; + $user_data['is_reviewer'] = $result_array[11]; + $user_data['is_editor'] = $result_array[12]; + $user_data['is_drafter'] = $result_array[13]; + $user_data['is_requester'] = $result_array[14]; + $user_data['is_system'] = $result_array[15]; + $user_data['is_public'] = $result_array[16]; + $user_data['is_locked'] = $result_array[17]; + $user_data['is_private'] = $result_array[18]; + $user_data['date_created'] = $result_array[19]; + $user_data['date_changed'] = $result_array[20]; + $user_data['date_synced'] = $result_array[21]; + $user_data['date_locked'] = $result_array[22]; + $user_data['settings'] = json_decode($result_array[23], TRUE); + + unset($result_array); + return c_base_return_array::s_new($user_data); } + unset($result_array); + } + unset($query_result); + + // at this ppint the user account likely does not exist in the database, so create it using any ldap information if available. + if (is_null($ldap_data)) { + $query_result = $database->do_query('insert into v_users_self_insert (name_human.first) values (null)'); + if (c_base_return::s_has_error($query_result)) { + return reservation_error_get_query('database->do_query(insert into v_users_self_insert)', __FUNCTION__, $query_result); + } + } + else { + $email = explode('@', $ldap_data['mail']); $parameters = array( - $id_sort, - $user_name, + $ldap_data['givenname'], + $ldap_data['sn'], + $ldap_data['cn'], + $email[0], + $email[1], + $ldap_data['employeenumber'], ); - $query_result = $database->do_query('select id, id_sort, id_external, name_human, address_email, is_private, is_locked, date_created, date_changed, settings from v_users_self where id_sort = $1 and name_machine = $2'); - unset($parameters); - - if ($query_result instanceof c_base_database_result) { - if ($query_result->number_of_rows()->get_value_exact() > 0) { - $result = $query_result->fetch_row(); - if (!($result instanceof c_base_return_false)) { - $result_array = $result->get_value(); - if (is_array($result_array) && !empty($result_array)) { - $result_array = $result->get_value(); - $user_data['id_user'] = $result_array[0]; - $user_data['id_sort'] = $result_array[1]; - $user_data['id_external'] = $result_array[2]; - $user_data['name_human'] = $result_array[3]; - $user_data['address_email'] = $result_array[4]; - $user_data['is_private'] = $result_array[5]; - $user_data['is_locked'] = $result_array[6]; - $user_data['date_created'] = $result_array[7]; - $user_data['date_changed'] = $result_array[8]; - $user_data['settings'] = json_decode($result_array[9], TRUE); - } - } - } + $query_result = $database->do_query('insert into v_users_self_insert (name_human.first, name_human.last, name_human.complete, address_email, id_external) values ($1, $2, $3, ($4, $5, TRUE), $6)', $parameters); + + if (c_base_return::s_has_error($query_result)) { + return reservation_error_get_query('database->do_query(insert into v_users_self_insert)', __FUNCTION__, $query_result); } + } + unset($query_result); + + + // try loading the user information again now that the user information exists in the database. + $parameters = array( + $id_sort, + $user_name, + ); + + $query_result = $database->do_query('select id, id_sort, id_external, name_machine, name_human, address_email, is_administer, is_manager, is_auditor, is_publisher, is_financer, is_reviewer, is_editor, is_drafter, is_requester, is_system, is_public, is_locked, is_private, date_created, date_changed, date_synced, date_locked, settings from v_users_self where id_sort = $1 and name_machine = $2', $parameters); + unset($parameters); + + if (c_base_return::s_has_error($query_result)) { + return reservation_error_get_query('database->do_query(select from v_users_self)', __FUNCTION__, $query_result); + } + + if ($query_result instanceof c_base_database_result && $query_result->number_of_rows()->get_value_exact() > 0) { + $result = $query_result->fetch_row(); unset($query_result); + + if (c_base_return::s_has_error($result)) { + return reservation_error_get_query('database->do_query(select from v_users_self)', __FUNCTION__, $result); + } + + $result_array = $result->get_value(); + unset($result); + + if (is_array($result_array) && !empty($result_array)) { + $result_array = $result->get_value(); + + $user_data = array(); + $user_data['id'] = $result_array[0]; + $user_data['id_sort'] = $result_array[1]; + $user_data['id_external'] = $result_array[2]; + $user_data['name_machine'] = $result_array[3]; + $user_data['name_human'] = $result_array[4]; + $user_data['address_email'] = $result_array[5]; + $user_data['is_administer'] = $result_array[6]; + $user_data['is_manager'] = $result_array[7]; + $user_data['is_auditor'] = $result_array[8]; + $user_data['is_publisher'] = $result_array[9]; + $user_data['is_financer'] = $result_array[10]; + $user_data['is_reviewer'] = $result_array[11]; + $user_data['is_editor'] = $result_array[12]; + $user_data['is_drafter'] = $result_array[13]; + $user_data['is_requester'] = $result_array[14]; + $user_data['is_system'] = $result_array[15]; + $user_data['is_public'] = $result_array[16]; + $user_data['is_locked'] = $result_array[17]; + $user_data['is_private'] = $result_array[18]; + $user_data['date_created'] = $result_array[19]; + $user_data['date_changed'] = $result_array[20]; + $user_data['date_synced'] = $result_array[21]; + $user_data['date_locked'] = $result_array[22]; + $user_data['settings'] = json_decode($result_array[23], TRUE); + + unset($result_array); + return c_base_return_array::s_new($user_data); + } + unset($result_array); } + unset($query_result); - return c_base_return_array::s_new($user_data); + + return c_base_return_array::s_new(array()); } /** @@ -307,6 +362,9 @@ /** * Get all roles assigned to the current user. * + * @todo: this might be unecessary as it may be automated via the user view table and sql triggers. + * @todo: review and update or delete this function as necessary. + * * @param c_base_database &$database * The database object. * @param array &$settings @@ -413,3 +471,54 @@ return new c_base_return_true(); } + + /** + * Builds a return object for a query. + * + * This functions is provided to simplify the return of specific code. + * Error handling is not performed, instead simple failsafes are used. + * + * @param string $operation_name + * The name of the operation, which is generally something like: database->do_query. + * @param string $function_name + * The name of the function. + * The caller should usually use __FUNCTION__ here. + * @param c_base_return $result + * The query return result. + * + * @return c_base_error + * A generated oepration failure error. + */ + function reservation_error_get_query($operation_name, $function_name, $result) { + if (!is_string($operation_name)) { + $operation_name = ''; + } + + if (!is_string($function_name)) { + $function_name = ''; + } + + $failure = new c_base_return_false(); + $found_errors = FALSE; + if ($result instanceof c_base_return) { + $errors = $result->get_error(); + if (is_array($errors)) { + $found_errors = TRUE; + + foreach ($errors as $error) { + $failure->set_error($error); + } + unset($error); + } + unset($errors); + } + + if (!$found_errors) { + $error = c_base_error::s_log(NULL, array('arguments' => array(':operation_name' => $operation_name, ':function_name' => $function_name)), i_base_error_messages::OPERATION_FAILURE); + $failure->set_error($error); + unset($error); + } + unset($found_errors); + + return $failure; + } diff --git a/program/reservation/reservation_paths.php b/program/reservation/reservation_paths.php index 0c0ad49..8014dbc 100644 --- a/program/reservation/reservation_paths.php +++ b/program/reservation/reservation_paths.php @@ -169,9 +169,8 @@ function reservation_build_login_page(&$html, $settings, $session) { * The current session. * * @return c_base_return_array|c_base_return_status - * FALSE on success. + * TRUE on success. * An array of problems on failure. - * FALSE with error bit set is returned on error. */ function reservation_attempt_login(&$database, &$settings, &$session) { $problems = array(); @@ -204,11 +203,12 @@ function reservation_attempt_login(&$database, &$settings, &$session) { $access_denied = FALSE; $error_messages = array(); $connected = reservation_database_connect($database); - if (!($connected instanceof c_base_return_true)) { + if (c_base_return::s_has_error($connected)) { // try to determine what the warning is. // this is not very accurate/efficient, but scanning the string appears to be the only way to identify the error. $errors = $connected->get_error(); + // @todo: walk through all errors instead of just checking the first. $error = reset($errors); unset($errors); @@ -233,6 +233,12 @@ function reservation_attempt_login(&$database, &$settings, &$session) { // it is a pity that postgresql doesn't differentiate the two. $access_denied = TRUE; } + else { + $problems[] = c_base_form_problem::s_create_error(NULL, 'Unable to login, reason: ' . $details['arguments'][':failure_reasons'][0]['message'] . '.'); + unset($details); + + return c_base_return_array::s_new($problems); + } } unset($details); @@ -289,7 +295,8 @@ function reservation_attempt_login(&$database, &$settings, &$session) { } } - if ($connected instanceof c_base_return_false) { + if (c_base_return::s_has_error($connected) || $connected instanceof c_base_return_false) { + // @todo: rewrite this function to handle multiple errors. if ($access_denied) { $problems[] = c_base_form_problem::s_create_error('login_form-username', 'Unable to login, an incorrect user or password has been specified.'); } @@ -314,96 +321,96 @@ function reservation_attempt_login(&$database, &$settings, &$session) { } unset($access_denied); + unset($connected); + + if (empty($problems)) { + unset($problems); + return new c_base_return_false(); + } + + return c_base_return_array::s_new($problems); } - else { - unset($access_denied); + unset($access_denied); - // @todo: add log entry. - #set_log_user($database, 'login'); + // @todo: add log entry. + #set_log_user($database, 'login'); - // @todo: load and store custom settings (loaded from the database and/or ldap). - #$session->set_id_user($user_id); - #$session->set_settings($user_data); + // @todo: load and store custom settings (loaded from the database and/or ldap). + #$session->set_settings($user_data); - // the session needs to be opened and the data needs to be saved on successful login. - $result = $session->do_connect(); - if (c_base_return::s_has_error($result)) { - $socket_error = $session->get_error_socket(); - if ($socket_error instanceof c_base_return_int) { - $problems[] = c_base_form_problem::s_create_error(NULL, 'Failed to load session, due to socket error (' . $socket_error->get_value_exact() . '): ' . @socket_strerror($socket_error->get_value_exact()) . '.'); - } - else { - $problems[] = c_base_form_problem::s_create_error(NULL, 'Failed to load session.'); - } - unset($socket_error); + // the session needs to be opened and the data needs to be saved on successful login. + $result = $session->do_connect(); + if (c_base_return::s_has_error($result)) { + $socket_error = $session->get_error_socket(); + if ($socket_error instanceof c_base_return_int) { + $problems[] = c_base_form_problem::s_create_error(NULL, 'Failed to load session, due to socket error (' . $socket_error->get_value_exact() . '): ' . @socket_strerror($socket_error->get_value_exact()) . '.'); } else { - $ldap = reservation_database_load_ldap_data($settings, $_POST['login_form-username'])->get_value(); - if ($ldap instanceof c_base_return_false || !is_array($ldap)) { - $ldap = array( - 'data' => NULL, - ); - } - - if (isset($ldap['status']) && $ldap['status'] instanceof c_base_return_false) { - $problems[] = c_base_form_problem::s_create_error('login_form-username', 'Failed to retrieve ldap information for specified user.'); + $problems[] = c_base_form_problem::s_create_error(NULL, 'Failed to load session.'); + } + unset($socket_error); + } + else { + $ldap = reservation_database_load_ldap_data($settings, $_POST['login_form-username'])->get_value(); + if ($ldap instanceof c_base_return_false || !is_array($ldap)) { + $ldap = array( + 'data' => NULL, + ); + } - // @todo: handle error situation. - } + if (isset($ldap['status']) && $ldap['status'] instanceof c_base_return_false) { + $problems[] = c_base_form_problem::s_create_error('login_form-username', 'Failed to retrieve ldap information for specified user.'); - $user_data = reservation_database_get_user_data($database, $_POST['login_form-username'], $ldap['data'])->get_value(); + // @todo: handle error situation. + } - if (is_array($user_data) && isset($user_data['id_user'])) { - $session->set_id_user($user_data['id_user']); - } + $user_data = reservation_database_get_user_data($database, $_POST['login_form-username'], $ldap['data'])->get_value(); - // @todo: get and use user id from $user_data. + // @todo: get and use user id from $user_data. - $pushed = $session->do_push($settings['session_expire'], $settings['session_max']); - $session->do_disconnect(); + $pushed = $session->do_push($settings['session_expire'], $settings['session_max']); + $session->do_disconnect(); - $cookie_login = NULL; - if (c_base_return::s_has_error($pushed)) { - $socket_error = $session->get_error_socket(); - if ($socket_error instanceof c_base_return_int) { - $problems = c_base_form_problem::s_create_error(NULL, 'Failed to push session, due to socket error (' . $socket_error->get_value_exact() . '): ' . @socket_strerror($socket_error->get_value_exact()) . '.'); - } - else { - $problems[] = c_base_form_problem::s_create_error(NULL, 'Failed to push session.'); - } - unset($socket_error); + $cookie_login = NULL; + if (c_base_return::s_has_error($pushed)) { + $socket_error = $session->get_error_socket(); + if ($socket_error instanceof c_base_return_int) { + $problems = c_base_form_problem::s_create_error(NULL, 'Failed to push session, due to socket error (' . $socket_error->get_value_exact() . '): ' . @socket_strerror($socket_error->get_value_exact()) . '.'); } else { - $session_expire = $session->get_timeout_expire()->get_value_exact(); - $cookie_login = $session->get_cookie(); + $problems[] = c_base_form_problem::s_create_error(NULL, 'Failed to push session.'); } + unset($socket_error); + } + else { + $session_expire = $session->get_timeout_expire()->get_value_exact(); + $cookie_login = $session->get_cookie(); + } - if ($cookie_login instanceof c_base_cookie) { - $cookie_login->set_expires($session_expire); - $cookie_login->set_max_age(NULL); + if ($cookie_login instanceof c_base_cookie) { + $cookie_login->set_expires($session_expire); + $cookie_login->set_max_age(NULL); - if ($pushed instanceof c_base_return_true) { - $data = array( - 'session_id' => $session->get_session_id()->get_value_exact(), - 'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unnecessary, but provided for debug purposes. - ); + if ($pushed instanceof c_base_return_true) { + $data = array( + 'session_id' => $session->get_session_id()->get_value_exact(), + 'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unnecessary, but provided for debug purposes. + ); - $cookie_login->set_value($data); - $session->set_cookie($cookie_login); - } + $cookie_login->set_value($data); + $session->set_cookie($cookie_login); } - unset($cookie_login); - unset($session_expire); - unset($pushed); } - unset($result); - + unset($cookie_login); + unset($session_expire); + unset($pushed); } + unset($result); unset($connected); if (empty($problems)) { unset($problems); - return new c_base_return_false(); + return new c_base_return_true(); } return c_base_return_array::s_new($problems); diff --git a/program/sessionize_accounts/source/php/sessionize_accounts-server.php b/program/sessionize_accounts/source/php/sessionize_accounts-server.php index 983a237..57649ba 100644 --- a/program/sessionize_accounts/source/php/sessionize_accounts-server.php +++ b/program/sessionize_accounts/source/php/sessionize_accounts-server.php @@ -32,7 +32,6 @@ * * Valid load response array keys: * - name: The user name associated with the session. - * - id_user: The numeric id of the user. * - password: The password associated with the session. * - expire: The session expiration timeout. * - max: The max session expiration timeout. @@ -41,7 +40,6 @@ * * A save request packet has the following keys: * - name: The username to associate with the session. - * - id_user: The numeric id of the user associated with this session. * - ip: The ip address to associate with the session. These sessions are ip-address specific. * - password: The password to associated with the session (must be defined, but may be NULL). * - expire: Request idle timeout interval, in seconds (this is a soft limit and cannot exceed the hard limit defined by this server). @@ -452,7 +450,6 @@ function main($argc, $argv) { $response['result'] = array( 'name' => $db_session['name'], - 'id_user' => (int) $db_session['id_user'], 'password' => $db_session['password'], 'expire' => $db_session['timeouts']['expire'], 'max' => $db_session['timeouts']['max'], @@ -487,10 +484,10 @@ function main($argc, $argv) { continue; } - if ((is_int($decoded_packet['id_user']) && $decoded_packet['id_user'] < 0) || !is_int($decoded_packet['id_user']) && (!is_string($decoded_packet['id_user']) || !(is_numeric($decoded_packet['id_user']) && (int) $decoded_packet['id_user'] >= 0))) { + if (!isset($decoded_packet['name']) || !is_string($decoded_packet['name']) || empty($decoded_packet['name'])) { $response['error'] = array( - 'target' => 'decoded_packet[id_user]', - 'message' => "No valid id_user was specified. A valid id_user integer, greater than or equal to 0, must be provided.", + 'target' => 'decoded_packet[name]', + 'message' => "No valid name was specified. A valid user name string, must be provided.", ); socket_write($client_socket, json_encode($response)); @@ -537,7 +534,6 @@ function main($argc, $argv) { $unique_id = $decoded_packet['name'] . '-' . uniqid(); $database['sessions'][$decoded_packet['ip']][$session_id] = array( 'name' => $decoded_packet['name'], - 'id_user' => (int) $decoded_packet['id_user'], 'password' => $decoded_packet['password'], 'timeouts' => array( 'id' => $unique_id, -- 1.8.3.1