User Synchronization in Oracle Express

#########################################    User Synchronization notification in Oracle Express ########################################################
-- Description: This process will notify by mail for following condition:
                               --  If user password mismatch  in Primary and Secondary Database
                               -- If a user in primary database does not exist in Secondary Database
                               -- If a user in secondary database does not exist in Primary Database

-- If you get mail regarding new user/password miss-match you need to fix that manually
-- I Needed to synchronize user in Oracle Express database and since Oracle Express don't have many features for replication therefore I have done this below mentioned way



#################################################
-- On Secondary database
#################################################
SQL> create user user_sync identified by <PWD>;

SQL> grant create session to user_sync;


SQL> grant select on sys.user$ to user_sync;


SQL> grant select on dba_users to user_sync;


#################################################
-- On primary database
#################################################
-- As sys user
SQL> create user user_sync identified by <PWD>;

SQL> grant create session to user_sync;


SQL> grant create procedure to user_sync;


SQL> grant select on sys.user$ to user_sync;


SQL> grant select on dba_users to user_sync;


SQL> grant create database link to user_sync;

SQL> grant all on UTL_SMTP to user_sync;


SQL>  grant all on UTL_TCP to user_sync;

SQL>
BEGIN
  DBMS_NETWORK_ACL_ADMIN.create_acl (
    acl          => 'user_sync.xml',
    description  => 'Purpose of the acl is user synchronization between XE database',
    principal    => 'USER_SYNC',
    is_grant     => TRUE,
    privilege    => 'connect',
    start_date   => SYSTIMESTAMP,
    end_date     => NULL);

  DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => 'user_sync.xml',
    host        => '127.0.0.1',
    lower_port  => 1,
    upper_port  => 9999);

  COMMIT;
END;
/


-- As user_sync User
 SQL> CREATE DATABASE LINK XE_USER_SYN CONNECT TO user_sync IDENTIFIED BY <PWD> USING 'STEGE_XE2';      -- Make sure you have enty in tnsnames.ora

SQL>
CREATE OR REPLACE PROCEDURE send_mail (p_to        IN VARCHAR2,
                                       p_from      IN VARCHAR2,
                                       p_subject   IN VARCHAR2,
                                       p_message   IN VARCHAR2,
                                       p_smtp_host IN VARCHAR2,
                                       p_smtp_port IN NUMBER DEFAULT 25)
AS
  l_mail_conn   UTL_SMTP.connection;
BEGIN
  l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
  UTL_SMTP.helo(l_mail_conn, p_smtp_host);
  UTL_SMTP.mail(l_mail_conn, p_from);
  UTL_SMTP.rcpt(l_mail_conn, p_to);

  UTL_SMTP.open_data(l_mail_conn);

  UTL_SMTP.write_data(l_mail_conn, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'To: ' || p_to || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'From: ' || p_from || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'Subject: ' || p_subject || UTL_TCP.crlf);
  UTL_SMTP.write_data(l_mail_conn, 'Reply-To: ' || p_from || UTL_TCP.crlf || UTL_TCP.crlf);

  UTL_SMTP.write_data(l_mail_conn, p_message || UTL_TCP.crlf || UTL_TCP.crlf);
  UTL_SMTP.close_data(l_mail_conn);

  UTL_SMTP.quit(l_mail_conn);
END;
/


SQL>
CREATE OR REPLACE PROCEDURE USER_SYNC IS
v_password VARCHAR2(30);
v_missing_user_primary VARCHAR2(30);
v_missing_user_secondery VARCHAR2(30);
BEGIN

select
listagg (s1.name, ',')
WITHIN GROUP
(ORDER BY s2.name) "Password"
into v_password
from sys.user$ s1
join dba_users d1 on(D1.USERNAME=S1.NAME)
join sys.user$@XE_USER_SYN s2 on(s2.name=S1.name)
join dba_users@XE_USER_SYN d2 on(D2.USERNAME=S2.NAME)
where D2.ACCOUNT_STATUS='OPEN'
and D2.ACCOUNT_STATUS='OPEN'
and S1.password!=S2.password
order by s1.name;

select
listagg (s1.name, ',')
WITHIN GROUP
(ORDER BY s1.name) "User Name"
into v_missing_user_primary
from sys.user$ s1
join dba_users d1 on(D1.USERNAME=S1.NAME)
where s1.name not in (select s2.name from sys.user$@XE_USER_SYN s2 join dba_users@XE_USER_SYN d2 on(D2.USERNAME=S2.NAME) and D2.ACCOUNT_STATUS='OPEN')
and D1.ACCOUNT_STATUS='OPEN';

select
listagg (s2.name, ',')
WITHIN GROUP
(ORDER BY s2.name) "User Name"
into v_missing_user_secondery
from sys.user$@XE_USER_SYN s2
join dba_users@XE_USER_SYN d2 on(D2.USERNAME=S2.NAME)
where s2.name not in (select s1.name from sys.user$ s1 join dba_users d1 on(D1.USERNAME=S1.NAME) and D1.ACCOUNT_STATUS='OPEN')
and D2.ACCOUNT_STATUS='OPEN' ;

if (v_password IS not null) THEN send_mail(p_to=> 'mohammad.nazmulhuda@netsize.com',p_from=> 'oracle@ipx.com',p_subject   => 'Password Need to Synchoronized XE',p_message   => v_password,p_smtp_host => '127.0.0.1'); end if;
if (v_missing_user_primary IS not null) THEN send_mail(p_to=> 'mohammad.nazmulhuda@netsize.com',p_from=> 'oracle@ipx.com',p_subject   => 'User need to create in Secondary Database XE',p_message   => v_missing_user_primary,p_smtp_host => '127.0.0.1'); end if;
if (v_missing_user_secondery IS not null) THEN send_mail(p_to=> 'mohammad.nazmulhuda@netsize.com',p_from=> 'oracle@ipx.com',p_subject   => 'User Need to Create in Primary Database XE',p_message   => v_missing_user_secondery,p_smtp_host => '127.0.0.1'); end if;
END;
/



-- Execute this procedure daily/hourly from script
SQL> EXECUTE USER_SYNC;

Comments