alter user kmourgos
     grant connect through oes_as
     with role all except ordmgmt;

create profile lim_connect limit
    connect_time 120;

create profile lim_fail_login limit
    failed_login_attempts 8;

create profile lim_connectime_faillog limit
    connect_time 120
    failed_login_attempts 8;

create profile lim_reuse_pass limit
    password_reuse_time 20
    password_reuse_max 5;

create context hr_security using vpd.emp_access;

create or replace package emp_access as
    procedure set_security_parameters;
end;

create or replace trigger vpd.set_security_parameters
    after logon on database
begin
    vpd.emp_access.set_security_parameters;
end;

create or replace package body get_predicates is

    function emp_select_restrict(owner varchar2, object_name varchar2)
            return varchar2 is
        ret_predicate varchar2(1000); -- cz klauzuli WHERE
    begin
        -- pozwala na przegldanie wierszy tabeli tylko wybranym pracownikom
        -- . . . sprawdzenie zmiennych kontekstowych i utworzenie predykatu
        return ret_predicate;
    end emp_select_restrict;

function emp_dml_restrict(owner varchar2, object_name varchar2)
                return varchar2 is
        ret_predicate varchar2(1000); -- cz klauzuli WHERE
    begin
        -- pozwala na wprowadzanie zmian w tabeli tylko wybranym pracownikom
        -- . . . sprawdzenie zmiennych kontekstowych i utworzenie predykatu
        return ret_predicate;
    end emp_dml_restrict;

end; -- treci pakietu

dbms_rls.add_policy (
    object_schema =>   'HR',
    object_name =>     'EMPLOYEES',
    policy_name =>     'EMP_SELECT_RESTRICT',
    function_schema => 'VPD',
    policy_function => 'get_predicates.emp_select_restrict',
    statement_types => 'SELECT',
    update_check =>    TRUE,
    enable =>          TRUE
);

dbms_rls.enable_policy(
    object_schema => 'HR',
    object_name =>   'EMPLOYEES',
    policy_name =>   'EMP_SELECT_RESTRICT',
    enable =>        FALSE
);

create user smavris identified by smavris702;
grant connect, resource to smavris;

create user dgrant identified by dgrant507;
grant connect, resource to dgrant;

create user kmourgos identified by kmourgos622;
grant connect, resource to kmourgos;

grant select on hr.employees to public;

create table hr.emp_login_map (employee_id, login_acct)
    as select employee_id, email from hr.employees;

grant select on hr.emp_login_map to public;

create user vpd identified by vpd439;
grant connect, resource, create any context, create public synonym to vpd;

connect vpd/vpd439@dw;

create context hr_security using vpd.emp_access;

create or replace package vpd.emp_access as
    procedure set_security_parameters;
end;

create or replace package body vpd.emp_access is

--
-- Po zalogowaniu si uytkownika naley wykona set_security_parameters, to
-- aby odczyta nazw uytkownika, odpowiadajc wartoci w kolumnie EMAIL
-- tabeli HR.EMPLOYEES.
--
-- kontekst USERENV zawiera charakterystyki uytkownika, takie jak
-- nazw uytkownika, adres IP jego poczenia i tak dalej.
--
-- w procedurze uywamy jedynie parametru SESSION_USER
-- z kontekstu USERENV.
--
    procedure set_security_parameters is
        emp_id_num number;
        emp_login varchar2(50);
    begin

        -- nazwa uytkownika bazy danych odpowiada adresowi poczty
        -- elektronicznej w tabeli HR.EMPLOYEES
        emp_login := sys_context('USERENV','SESSION_USER');

        dbms_session.set_context('HR_SECURITY','USERNAME',emp_login);

        -- odczytanie numeru identyfikacyjnego pracownika, aby ustanowi uprawnienia menedera
        -- trzeba jednak omin innych uytkownikw bazy danych,
        -- ktrzy nie wystpuj w tabeli EMPLOYEES
        begin
            select employee_id into emp_id_num
                from hr.emp_login_map where login_acct = emp_login;

            dbms_session.set_context('HR_SECURITY','EMP_ID',emp_id_num);
        exception
            when no_data_found then
                dbms_session.set_context('HR_SECURITY','EMP_ID',0);
        end;

        -- w nastpnych zapytaniach zbir zwracanych wierszy bdzie ograniczony
        -- na podstawie wartoci emp_id

    end; -- koniec procedury

end; -- koniec treci pakietu

grant execute on vpd.emp_access to PUBLIC;
create public synonym emp_access for vpd.emp_access;

connect sys/sys727@dw as sysdba;

create or replace trigger vpd.set_security_parameters
    after logon on database
begin
    vpd.emp_access.set_security_parameters;
end;

connect vpd/vpd439@dw;

create or replace package vpd.get_predicates as

    -- uwaga: funkcje zabezpieczajce ZAWSZE posiadaj dwa parametry:
    -- nazw waciciela tabeli oraz nazw tabeli

    function emp_select_restrict
         (owner varchar2, object_name varchar2) return varchar2;

    -- tutaj mona dopisa kolejne funkcje dla operacji INSERT, DELETE i tak dalej

end get_predicates;


create or replace package body vpd.get_predicates is

    function emp_select_restrict
         (owner varchar2, object_name varchar2) return varchar2 is

        ret_predicate varchar2(1000); -- cz klauzuli WHERE

    begin
        -- pozwala pracownikowi na dostp do danych dotyczcych jego samego
        -- lub jego bezporednich podwadnych
        ret_predicate := 'EMPLOYEE_ID = ' ||
                         sys_context('HR_SECURITY','EMP_ID') ||
                         ' OR MANAGER_ID = ' ||
                         sys_context('HR_SECURITY','EMP_ID');
        return ret_predicate;
    end emp_select_restrict;

end; -- koniec pakietu

grant execute on vpd.get_predicates to PUBLIC;
create public synonym get_predicates for vpd.get_predicates;

dbms_rls.add_policy (
         object_schema => 'HR',
         object_name => 'EMPLOYEES',
         policy_name => 'EMP_SELECT_RESTRICT',
         function_schema => 'VPD',
         policy_function => 'get_predicates.emp_select_restrict',
         statement_types => 'SELECT',
         update_check => TRUE,
         enable => TRUE
);

create or replace package body vpd.get_predicates is

    function emp_select_restrict
         (owner varchar2, object_name varchar2) return varchar2 is

        ret_predicate varchar2(1000); -- cz klauzuli WHERE

    begin
        -- pozwala pracownikowi na dostp do danych dotyczcych jego samego,
        -- chyba e posiada wysoki poziom zabezpiecze
        if sys_context('HR_SECURITY','SEC_LEVEL') = 'HIGH' then
            ret_predicate := ''; -- brak ogranicze w klauzuli WHERE
        else
            ret_predicate := 'EMPLOYEE_ID = ' ||
                             sys_context('HR_SECURITY','EMP_ID') ||
                             ' OR MANAGER_ID = ' ||
                             sys_context('HR_SECURITY','EMP_ID');
        end if;
        return ret_predicate;
    end emp_select_restrict;

end; -- koniec pakietu

dbms_rls.add_policy (
         object_schema => 'HR',
         object_name => 'EMPLOYEES',
         policy_name => 'EMP_SELECT_RESTRICT',
         function_schema => 'VPD',
         policy_function => 'get_predicates.emp_select_restrict',
         statement_types => 'SELECT',
         update_check => TRUE,
         enable => TRUE,
         sec_relevant_cols => 'SALARY',
         sec_relevant_cols_opt => dbms_rls.all_rows
);

begin
    dbms_fga.add_policy(
        object_schema => 'HR',
        object_name => 'EMPLOYEES',
        policy_name => 'SAL_SELECT_AUDIT',
        audit_condition => 'instr(job_id,''_MAN'') > 0',
        audit_column => 'SALARY'
    );
end;

