But I regularly find myself in a place where connections are difficult and I cannot access the database or some services from my development environment. In these cases a complete environment installed locally on the laptop is an advantage.
Installation
I use Ubuntu 18.04 as my operating system and Ubuntu describes very well how to do it in the official documentation, so I just list the commands, where I added instructions to update the database to release 11:$sudo apt-get install curl ca-certificates
(only if curl not already installed)$curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
$sudo apt update
$sudo apt install postgresql-11
$sudo -u postgres psql template1
postgres=# ALTER ROLE postgres with encrypted password 'YOUR_PASSWORD';
postgres=# \q
$sudo nano /etc/postgresql/11/main/pg_hba.conf
local all postgres md5
- <ctrl>X and answer yes
$sudo systemctl restart postgresql.service
Database
The management of the database requires a graphical tool to avoid a lot of typing work. I use the Ultimate version of Intellj that I already have for business reasons.The development database is simply called laboratory. The PostgreSQL documentation is complete and easy to read so I'll just list the SQL statements I used to create the users and the database.
At the prompt login as postgres
$ psql postgres postgres
.create role labadmin login createrole password 'labadmin';
comment on role labadmin is 'login for laboratory database administration';
create database laboratory owner labadmin;
comment on database laboratory is 'database for experiments';
postgres=# \i labadmin.sql
create role labuser login password 'labuser';
comment on role labuser is 'login for applications';
create schema business;
comment on schema business is 'schema containing all business related entities';
postgres=# \i laboratory.sql
drop table if exists business.B_LOGINS cascade;
drop sequence if exists business.B_LOGINS_id_seq cascade;
drop table if exists business.B_PERSONS cascade;
drop sequence if exists business.B_PERSONS_id_seq;
-- PERSONS --------------------------------------------------------------------
create sequence business.B_PERSONS_id_seq minvalue 1000;
create table business.B_PERSONS
(
id numeric(16) default nextval('business.B_PERSONS_id_seq') not null,
firstname varchar(64) not null,
lastname varchar(64) not null,
qualifier varchar(16),
deleted timestamp
);
comment on table business.B_PERSONS is 'all people';
comment on column business.B_PERSONS.id is 'autoincremented primary key';
comment on column business.B_PERSONS.firstname is 'the name of the person (mandatory)';
comment on column business.B_PERSONS.lastname is 'the surname of the person';
comment on column business.B_PERSONS.qualifier is 'the role of the person: ADMIN, OPERATOR, CUSTOMER or undefined (NULL)';
comment on column business.B_PERSONS.deleted is 'the timestamp of the deletion';
alter table business.B_PERSONS
add constraint B_PERSONS_pk
primary key (id);
-- LOGINS ---------------------------------------------------------------------
create sequence business.B_LOGINS_id_seq minvalue 1000;
create table business.B_LOGINS
(
id numeric(16) default nextval('business.B_LOGINS_id_seq')
constraint B_LOGINS_pk
primary key,
b_persons_id numeric(16) not null
constraint B_LOGINS_b_persons_id_fk
references business.b_persons,
name varchar(32) not null,
password varchar(32) not null,
locked numeric(1) not null,
opt_structure varchar(4000),
deleted timestamp
);
create unique index b_logins_name_uindex
on business.b_logins (name);
comment on table business.B_LOGINS is 'all people logins';
comment on column business.B_LOGINS.id is 'autoincremented primary key';
comment on column business.B_LOGINS.b_persons_id is 'the ID of the related person';
comment on column business.B_LOGINS.name is 'UserLogin name or alias';
comment on column business.B_LOGINS.password is 'UserLogin password';
comment on column business.B_LOGINS.locked is '0 - false (UserLogin not locked), 1 - true (UserLogin locked)';
comment on column business.B_LOGINS.opt_structure is 'the structured string to handle One Time passwords';
comment on column business.B_LOGINS.deleted is 'the timestamp of the deletion';
postgres=# \i laboratory_tables.sql
-- LOGINS ---------------------------------------------------------------------
create or replace view business.LOGINS as
select id, b_persons_id as persons_id, name, password, locked, opt_structure
from business.b_logins
where deleted is null;
comment on view business.logins is 'returns all logins that aren''t deleted';
-- PERSONS --------------------------------------------------------------------
create or replace view business.PERSONS as
select id, firstname, lastname, qualifier
from business.b_persons
where deleted is null;
comment on view business.persons is 'returns all persons that aren''t deleted';
postgres=# \i laboratory_views.sql
drop function if exists business.check_if_person_deleted_trigger cascade;
drop function if exists business.check_if_person_deleted_trigger cascade;
create function business.check_if_person_deleted_trigger()
returns trigger as $b_login$
declare
delvar timestamp;
relid numeric(16);
delcur cursor for select deleted from business.b_persons where business.b_persons.id = relid;
begin
if (TG_OP = 'UPDATE') then
relid := NEW.b_persons_id;
open delcur;
fetch delcur into delvar;
close delcur;
raise notice 'new.deleted = %', NEW.deleted;
raise notice 'delvar = %', delvar;
if (NEW.deleted isnull AND delvar is not null) then
raise exception 'Cannot undelete the UserLogin with ID % if the user is deleted!', relid;
end if;
end if;
return null;
end; $b_login$
language PLPGSQL;
drop function if exists business.delete_person_trigger cascade;
create function business.delete_person_trigger()
returns trigger as $b_persons$
begin
if (TG_OP = 'UPDATE') then
update business.b_logins
set deleted = current_timestamp
where b_persons_id = NEW.id;
end if;
return null;
end; $b_persons$
language PLPGSQL;
alter function business.delete_person_trigger() owner to labadmin;
postgres=# \i laboratory_functions.sql
-- B_LOGINS -------------------------------------------------------------------
drop trigger if exists b_logins_check_if_person_deleted on business.b_logins;
create trigger b_logins_check_if_person_deleted
after update of deleted on business.b_logins
for each row
when (NEW.deleted is null)
execute procedure business.check_if_person_deleted_trigger();
-- B_PERSONS ------------------------------------------------------------------
drop trigger if exists b_persons_delete_login on business.b_persons;
create trigger b_persons_delete_login
after update of deleted on business.b_persons
for each row
when (NEW.deleted is not null)
execute procedure business.delete_person_trigger();
postgres=# \i laboratory_triggers.sql
-- DATABASE -------------------------------------------------------------------
-- DATABASE -------------------------------------------------------------------
revoke connect on database laboratory from labuser;
grant connect on database laboratory to labuser;
-- SCHEMA BUSINESS ------------------------------------------------------------
revoke usage on schema business from labuser;
grant usage on schema business to labuser;
-- FUNCTIONS ..................................................................
revoke all privileges on function business.check_if_person_deleted_trigger() from labuser;
grant execute on function business.check_if_person_deleted_trigger() to labuser;
revoke all privileges on function business.delete_person_trigger() from labuser;
grant execute on function business.delete_person_trigger() to labuser;
-- LOGINS ---------------------------------------------------------------------
revoke all privileges on business.b_logins_id_seq from labuser;
revoke all privileges on business.logins from labuser;
grant usage on sequence business.b_logins_id_seq to labuser;
grant select, insert, update, delete on table business.logins to labuser;
-- PERSONS --------------------------------------------------------------------
revoke all privileges on business.b_persons_id_seq from labuser;
revoke all privileges on business.persons from labuser;
grant usage on sequence business.b_persons_id_seq to labuser;
grant select, insert, update, delete on table business.persons to labuser;
postgres=# \i laboratory_grants.sql
postgres=# \q
At the prompt login as labuser
$ psql laboratory labuser
.insert into business.persons (firstname, lastname, qualifier) values ('Lovely', 'Girl', 'CUSTOMER');
insert into business.persons (firstname, lastname, qualifier) values ('Pretty', 'Woman', 'CUSTOMER');
insert into business.persons (firstname, lastname, qualifier) values ('Nice', 'Guy', 'CUSTOMER');
insert into business.persons (firstname, lastname, qualifier) values ('Handsome', 'Man', 'CUSTOMER');
insert into business.persons (firstname, lastname, qualifier) values ('Cocco', 'Drilli', null);
postgres=# \i persons.sql
insert into business.logins (persons_id, name, password, locked) values (1000, 'lovely', 'girl', 0);
insert into business.logins (persons_id, name, password, locked) values (1001, 'pretty', 'woman', 0);
insert into business.logins (persons_id, name, password, locked) values (1002, 'nice', 'guy', 0);
insert into business.logins (persons_id, name, password, locked) values (1003, 'handsome', 'man', 0);
insert into business.logins (persons_id, name, password, locked) values (1004, 'cocco', 'drilli', 0);
postgres=# \i login.sql
No comments:
Post a Comment