diff --git a/core/db_connector.js b/core/db_connector.js index de47051..d51369c 100644 --- a/core/db_connector.js +++ b/core/db_connector.js @@ -13,6 +13,7 @@ const { ServerError } = require("./server_errors"); //Типовая ошибк const { makeModuleFullPath, validateObject } = require("./utils"); //Вспомогательные функции const prmsDBConnectorSchema = require("../models/prms_db_connector"); //Схемы валидации параметров функций модуля const intfDBConnectorModuleSchema = require("../models/intf_db_connector_module"); //Схема валидации интерфейса модуля взаимодействия с БД +const objServiceSchema = require("../models/obj_service"); //Схема валидации сервиса const objServicesSchema = require("../models/obj_services"); //Схема валидации списка сервисов const objServiceFunctionsSchema = require("../models/obj_service_functions"); //Схема валидации списка функций сервиса const objQueueSchema = require("../models/obj_queue"); //Схема валидации сообщения очереди обмена @@ -197,7 +198,7 @@ class DBConnector extends EventEmitter { "Список функций сервиса" ); if (sCheckResult) throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult); - //Вернём добавленную запись + //Успешно - отдаём список функций сервиса return res; } catch (e) { throw new ServerError(SERR_DB_EXECUTE, e.message); @@ -209,6 +210,165 @@ class DBConnector extends EventEmitter { throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); } } + //Получить контекст сервиса + async getServiceContext(prms) { + //Работаем только при наличии подключения + if (this.bConnected) { + //Проверяем структуру переданного объекта с параметрами для получения контекста сервиса + let sCheckResult = validateObject( + prms, + prmsDBConnectorSchema.getServiceContext, + "Параметры функции считывания контекста сервиса" + ); + //Если структура объекта в норме + if (!sCheckResult) { + try { + //Подготовим параметры для передачи в БД + let getServiceContextData = _.cloneDeep(prms); + getServiceContextData.connection = this.connection; + //И выполним считывание контекста сервиса + let res = await this.connector.getServiceContext(getServiceContextData); + //Валидируем полученный ответ + sCheckResult = validateObject(res, objServiceSchema.ServiceCtx, "Контекст сервиса"); + if (sCheckResult) throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult); + //Успешно - отдаём контекст считанный сервиса + return res; + } catch (e) { + throw new ServerError(SERR_DB_EXECUTE, e.message); + } + } else { + throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult); + } + } else { + throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); + } + } + //Установить контекст сервиса + async setServiceContext(prms) { + //Работаем только при наличии подключения + if (this.bConnected) { + //Проверяем структуру переданного объекта с параметрами для установки контекста сервиса + let sCheckResult = validateObject( + prms, + prmsDBConnectorSchema.setServiceContext, + "Параметры функции установки контекста сервиса" + ); + //Если структура объекта в норме + if (!sCheckResult) { + try { + //Подготовим параметры для передачи в БД + let setServiceContextData = _.cloneDeep(prms); + setServiceContextData.connection = this.connection; + //И выполним установку контекста сервиса + await this.connector.setServiceContext(setServiceContextData); + //Успешно - возвращаем ничего + return; + } catch (e) { + throw new ServerError(SERR_DB_EXECUTE, e.message); + } + } else { + throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult); + } + } else { + throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); + } + } + //Очистить контекст сервиса + async clearServiceContext(prms) { + //Работаем только при наличии подключения + if (this.bConnected) { + //Проверяем структуру переданного объекта с параметрами для очистки контекста сервиса + let sCheckResult = validateObject( + prms, + prmsDBConnectorSchema.clearServiceContext, + "Параметры функции очистки контекста сервиса" + ); + //Если структура объекта в норме + if (!sCheckResult) { + try { + //Подготовим параметры для передачи в БД + let clearServiceContextData = _.cloneDeep(prms); + clearServiceContextData.connection = this.connection; + //И выполним очистку контекста сервиса + await this.connector.clearServiceContext(clearServiceContextData); + //Успешно - возвращаем ничего + return; + } catch (e) { + throw new ServerError(SERR_DB_EXECUTE, e.message); + } + } else { + throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult); + } + } else { + throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); + } + } + //Проверить аутентифицированность сервиса + async isServiceAuth(prms) { + //Работаем только при наличии подключения + if (this.bConnected) { + //Проверяем структуру переданного объекта с параметрами для проверки аутентифицированности сервиса + let sCheckResult = validateObject( + prms, + prmsDBConnectorSchema.isServiceAuth, + "Параметры функции проверки аутентифицированности сервиса" + ); + //Если структура объекта в норме + if (!sCheckResult) { + try { + //Подготовим параметры для передачи в БД + let isServiceAuthData = _.cloneDeep(prms); + isServiceAuthData.connection = this.connection; + //И выполним проверку атентифицированности сервиса + let res = await this.connector.isServiceAuth(isServiceAuthData); + //Валидируем результат + if (![objServiceSchema.NIS_AUTH_NO, objServiceSchema.NIS_AUTH_YES].includes(res)) + throw new ServerError( + SERR_OBJECT_BAD_INTERFACE, + "Неожиданный ответ функции проверки аутентифицированности сервиса" + ); + //Успешно - возвращаем то, что вернула функция проверки + return res; + } catch (e) { + throw new ServerError(SERR_DB_EXECUTE, e.message); + } + } else { + throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult); + } + } else { + throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); + } + } + //Поставить в очередь задание на аутентификацию сервиса + async putServiceAuthInQueue(prms) { + //Работаем только при наличии подключения + if (this.bConnected) { + //Проверяем структуру переданного объекта с параметрами постановки в очередь задания на аутентификацию сервиса + let sCheckResult = validateObject( + prms, + prmsDBConnectorSchema.putServiceAuthInQueue, + "Параметры функции постановки в очередь задания на аутентификацию сервиса" + ); + //Если структура объекта в норме + if (!sCheckResult) { + try { + //Подготовим параметры для передачи в БД + let putServiceAuthInQueueData = _.cloneDeep(prms); + putServiceAuthInQueueData.connection = this.connection; + //И выполним постановку в очередь задания на аутентификацию сервиса + await this.connector.putServiceAuthInQueue(putServiceAuthInQueueData); + //Успешно - возвращаем ничего + return; + } catch (e) { + throw new ServerError(SERR_DB_EXECUTE, e.message); + } + } else { + throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult); + } + } else { + throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); + } + } //Запись в журнал работы async putLog(prms) { //Работаем только при наличии подключения diff --git a/db/PKG_EXS.pck b/db/PKG_EXS.pck index 655ea4e..be9a884 100644 --- a/db/PKG_EXS.pck +++ b/db/PKG_EXS.pck @@ -54,6 +54,12 @@ create or replace package PKG_EXS as SUNAVLBL_NTF_SIGN_NO constant varchar2(40) := 'UNAVLBL_NTF_NO'; -- ( ) SUNAVLBL_NTF_SIGN_YES constant varchar2(40) := 'UNAVLBL_NTF_YES'; -- ( ) + /* - */ + NERR_NTF_SIGN_NO constant EXSSERVICEFN.ERR_NTF_SIGN%type := 0; -- + NERR_NTF_SIGN_YES constant EXSSERVICEFN.ERR_NTF_SIGN%type := 1; -- + SERR_NTF_SIGN_NO constant varchar2(40) := 'ERR_NTF_SIGN_NO'; -- ( ) + SERR_NTF_SIGN_YES constant varchar2(40) := 'ERR_NTF_SIGN_YES'; -- ( ) + /* - */ NLOG_STATE_INF constant EXSLOG.LOG_STATE%type := 0; -- NLOG_STATE_WRN constant EXSLOG.LOG_STATE%type := 1; -- @@ -86,10 +92,22 @@ create or replace package PKG_EXS as NINC_EXEC_CNT_NO constant number(1) := 0; -- NINC_EXEC_CNT_YES constant number(1) := 1; -- - /* - */ + /* - */ NQUEUE_EXEC_NO constant number(1) := 0; -- NQUEUE_EXEC_YES constant number(1) := 1; -- + /* - */ + NIS_AUTH_YES constant EXSSERVICE.IS_AUTH%type := 1; -- + NIS_AUTH_NO constant EXSSERVICE.IS_AUTH%type := 0; -- + SIS_AUTH_YES constant varchar2(40) := 'IS_AUTH_YES'; -- ( ) + SIS_AUTH_NO constant varchar2(40) := 'IS_AUTH_NO'; -- ( ) + + /* - */ + NAUTH_ONLY_YES constant EXSSERVICEFN.AUTH_ONLY%type := 1; -- + NAUTH_ONLY_NO constant EXSSERVICEFN.AUTH_ONLY%type := 0; -- + SAUTH_ONLY_YES constant varchar2(40) := 'AUTH_ONLY_YES'; -- ( ) + SAUTH_ONLY_NO constant varchar2(40) := 'AUTH_ONLY_NO'; -- ( ) + /* - */ SPRC_RESP_ARGS constant varchar2(80) := 'NIDENT,IN,NUMBER;NSRV_TYPE,IN,NUMBER;NEXSQUEUE,IN,NUMBER;'; -- @@ -119,8 +137,7 @@ create or replace package PKG_EXS as ( NIDENT in number, -- SSUB_CONTAINER in varchar2 := null -- - ) - return varchar2; -- + ) return varchar2; -- /* */ procedure UTL_CONTAINER_PURGE @@ -135,8 +152,7 @@ create or replace package PKG_EXS as DEXEC_DATE in date, -- NRETRY_SCHEDULE in number, -- (. NRETRY_SCHEDULE_*) NRETRY_STEP in number -- - ) - return date; -- + ) return date; -- /* */ function UTL_SCHED_CHECK_EXEC @@ -145,8 +161,7 @@ create or replace package PKG_EXS as NRETRY_SCHEDULE in number, -- (. NRETRY_SCHEDULE_*) NRETRY_STEP in number, -- DEXEC in date := sysdate -- , - ) - return boolean; -- + ) return boolean; -- /* */ procedure PRC_RESP_ARG_STR_SET @@ -243,12 +258,60 @@ create or replace package PKG_EXS as RCSERVICE out sys_refcursor -- ); + /* */ + procedure SERVICE_CTX_GET + ( + NFLAG_SMART in number, -- + NEXSSERVICE in number, -- . + RCSERVICE_CTX out sys_refcursor -- + ); + + /* */ + procedure SERVICE_CTX_SET + ( + NEXSSERVICE in number, -- . + SCTX in varchar2, -- + DCTX_EXP in date -- + ); + + /* */ + procedure SERVICE_CTX_CLEAR + ( + NEXSSERVICE in number -- . + ); + + /* */ + function SERVICE_IS_AUTH + ( + NEXSSERVICE in number -- . + ) return number; -- (. NIS_AUTH_*) + + /* */ + procedure SERVICE_AUTH_FN_FIND + ( + NFLAG_SMART in number, -- + NEXSSERVICE in number, -- . + REXSSERVICEFN out EXSSERVICEFN%rowtype -- + ); + + /* */ + procedure SERVICE_AUTH_PUT_INQUEUE + ( + NEXSSERVICE in number -- . + ); + /* */ procedure SERVICES_GET ( RCSERVICES out sys_refcursor -- ); + /* */ + procedure SERVICES_AUTH_GET + ( + RCSERVICES_AUTH out sys_refcursor -- + ); + /* */ procedure SERVICEFN_GET ( @@ -277,8 +340,13 @@ create or replace package PKG_EXS as NFLAG_SMART in number, -- (0 - , 1 - ) SEXSSERVICE in varchar2, -- SEXSSERVICEFN in varchar2 -- - ) - return number; -- . + ) return number; -- . + + /* */ + function SERVICEFN_CHECK_INCMPL_INQUEUE + ( + NEXSSERVICEFN in number -- . + ) return boolean; -- (true - , false - ) /* */ procedure LOG_GET @@ -325,8 +393,7 @@ create or replace package PKG_EXS as function QUEUE_SRV_TYPE_SEND_EXEC_CHECK ( NEXSQUEUE in number -- . - ) - return number; -- (. NQUEUE_EXEC_*) + ) return number; -- (. NQUEUE_EXEC_*) /* */ procedure QUEUE_SRV_TYPE_SEND_GET @@ -682,8 +749,7 @@ create or replace package body PKG_EXS as ( NIDENT in number, -- SSUB_CONTAINER in varchar2 := null -- - ) - return varchar2 -- + ) return varchar2 -- is /* */ function CONTAINER_MAKE_NAME @@ -731,8 +797,7 @@ create or replace package body PKG_EXS as DEXEC_DATE in date, -- NRETRY_SCHEDULE in number, -- (. NRETRY_SCHEDULE_*) NRETRY_STEP in number -- - ) - return date -- + ) return date -- is begin /* , - */ @@ -790,8 +855,7 @@ create or replace package body PKG_EXS as NRETRY_SCHEDULE in number, -- (. NRETRY_SCHEDULE_*) NRETRY_STEP in number, -- DEXEC in date := sysdate -- , - ) - return boolean -- + ) return boolean -- is DEXEC_NEXT date; -- H begin @@ -1056,6 +1120,173 @@ create or replace package body PKG_EXS as RNLIST_BASE_CLEAR(NIDENT => NIDENT); end SERVICE_GET; + /* */ + procedure SERVICE_CTX_GET + ( + NFLAG_SMART in number, -- + NEXSSERVICE in number, -- . + RCSERVICE_CTX out sys_refcursor -- + ) + is + REXSSERVICE EXSSERVICE%rowtype; -- + begin + /* */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => NFLAG_SMART, NRN => NEXSSERVICE); + /* */ + open RCSERVICE_CTX for + select T.RN "nId", + T.CTX "sCtx", + T.CTX_EXP "dCtxExp", + TO_CHAR(T.CTX_EXP, 'dd.mm.yyyy hh24:mi:ss') "sCtxExp", + T.IS_AUTH "nIsAuth", + DECODE(T.IS_AUTH, NIS_AUTH_YES, SIS_AUTH_YES, NIS_AUTH_NO, SIS_AUTH_NO) "sIsAuth" + from EXSSERVICE T + where T.RN = REXSSERVICE.RN; + end SERVICE_CTX_GET; + + /* */ + procedure SERVICE_CTX_SET + ( + NEXSSERVICE in number, -- . + SCTX in varchar2, -- + DCTX_EXP in date -- + ) + is + REXSSERVICE EXSSERVICE%rowtype; -- + begin + /* */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => NEXSSERVICE); + /* , */ + if (SCTX is null) then + P_EXCEPTION(0, ' .'); + end if; + /* */ + update EXSSERVICE T + set T.CTX = SCTX, + T.CTX_EXP = DCTX_EXP, + T.IS_AUTH = NIS_AUTH_YES + where T.RN = REXSSERVICE.RN; + end SERVICE_CTX_SET; + + /* */ + procedure SERVICE_CTX_CLEAR + ( + NEXSSERVICE in number -- . + ) + is + REXSSERVICE EXSSERVICE%rowtype; -- + begin + /* */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => NEXSSERVICE); + /* */ + update EXSSERVICE T + set T.CTX = null, + T.CTX_EXP = null, + T.IS_AUTH = NIS_AUTH_NO + where T.RN = REXSSERVICE.RN; + end SERVICE_CTX_CLEAR; + + /* */ + function SERVICE_IS_AUTH + ( + NEXSSERVICE in number -- . + ) return number -- (. NIS_AUTH_*) + is + NRES PKG_STD.TNUMBER; -- + REXSSERVICE EXSSERVICE%rowtype; -- + begin + /* */ + NRES := NIS_AUTH_NO; + /* */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => NEXSSERVICE); + /* */ + if (REXSSERVICE.IS_AUTH = NIS_AUTH_YES) then + /* */ + if (REXSSERVICE.CTX_EXP is not null) then + /* */ + if (REXSSERVICE.CTX_EXP > sysdate) then + /* */ + NRES := NIS_AUTH_YES; + end if; + else + /* - */ + NRES := NIS_AUTH_YES; + end if; + end if; + /* */ + return NRES; + end SERVICE_IS_AUTH; + + /* */ + procedure SERVICE_AUTH_FN_FIND + ( + NFLAG_SMART in number, -- + NEXSSERVICE in number, -- . + REXSSERVICEFN out EXSSERVICEFN%rowtype -- + ) + is + REXSSERVICE EXSSERVICE%rowtype; -- + begin + /* */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => NFLAG_SMART, NRN => NEXSSERVICE); + /* */ + if (REXSSERVICE.RN is not null) then + /* */ + begin + select T.* + into REXSSERVICEFN + from EXSSERVICEFN T + where T.PRN = REXSSERVICE.RN + and T.FN_TYPE = NFN_TYPE_LOGIN; + exception + when TOO_MANY_ROWS then + P_EXCEPTION(NFLAG_SMART, + ' "%s" .', + REXSSERVICE.CODE); + when NO_DATA_FOUND then + P_EXCEPTION(NFLAG_SMART, + ' "%s" .', + REXSSERVICE.CODE); + end; + end if; + end SERVICE_AUTH_FN_FIND; + + /* */ + procedure SERVICE_AUTH_PUT_INQUEUE + ( + NEXSSERVICE in number -- . + ) + is + pragma autonomous_transaction; + REXSSERVICEFN_AUTH EXSSERVICEFN%rowtype; -- + NAUTH_EXSQUEUE PKG_STD.TREF; -- . + begin + /* */ + SERVICE_AUTH_FN_FIND(NFLAG_SMART => 0, NEXSSERVICE => NEXSSERVICE, REXSSERVICEFN => REXSSERVICEFN_AUTH); + /* , */ + if (not SERVICEFN_CHECK_INCMPL_INQUEUE(NEXSSERVICEFN => REXSSERVICEFN_AUTH.RN)) then + /* */ + SERVICE_CTX_CLEAR(NEXSSERVICE => REXSSERVICEFN_AUTH.PRN); + /* */ + P_EXSQUEUE_BASE_INSERT(DIN_DATE => sysdate, + SIN_AUTHID => UTILIZER(), + NEXSSERVICEFN => REXSSERVICEFN_AUTH.RN, + DEXEC_DATE => null, + NEXEC_CNT => 0, + NEXEC_STATE => NQUEUE_EXEC_STATE_INQUEUE, + SEXEC_MSG => null, + BMSG => null, + BRESP => null, + NEXSQUEUE => null, + NLNK_COMPANY => null, + NLNK_DOCUMENT => null, + SLNK_UNITCODE => null, + SOPTIONS => null, + NRN => NAUTH_EXSQUEUE); + end if; + commit; + end SERVICE_AUTH_PUT_INQUEUE; + /* */ procedure SERVICES_GET ( @@ -1078,7 +1309,41 @@ create or replace package body PKG_EXS as /* */ RNLIST_BASE_CLEAR(NIDENT => NIDENT); end SERVICES_GET; - + + /* */ + procedure SERVICES_AUTH_GET + ( + RCSERVICES_AUTH out sys_refcursor -- + ) + is + NIDENT PKG_STD.TREF; -- + NTMP PKG_STD.TREF; -- . + begin + /* */ + NIDENT := GEN_IDENT(); + /* */ + for C in (select T.RN + from EXSSERVICE T + where T.IS_AUTH = NIS_AUTH_NO + and exists (select FN.RN + from EXSSERVICEFN FN + where FN.PRN = T.RN + and FN.FN_TYPE = NFN_TYPE_LOGIN) + and exists (select FN.RN + from EXSSERVICEFN FN + where FN.PRN = T.RN + and FN.AUTH_ONLY = NAUTH_ONLY_YES + and FN.FN_TYPE <> NFN_TYPE_LOGIN)) + loop + /* . */ + RNLIST_BASE_INSERT(NIDENT => NIDENT, NDOCUMENT => C.RN, NRN => NTMP); + end loop; + /* */ + SERVICE_GET(NIDENT => NIDENT, RCSERVICE => RCSERVICES_AUTH); + /* */ + RNLIST_BASE_CLEAR(NIDENT => NIDENT); + end SERVICES_AUTH_GET; + /* */ procedure SERVICEFN_GET ( @@ -1123,7 +1388,12 @@ create or replace package body PKG_EXS as M.CODE "sMsgCode", DECODE(M.PRC_RESP, null, null, UTL_STORED_MAKE_LINK(SPROCEDURE => M.PRC_RESP, SPACKAGE => M.PKG_RESP)) "sPrcResp", M.APPSRV_BEFORE "sAppSrvBefore", - M.APPSRV_AFTER "sAppSrvAfter" + M.APPSRV_AFTER "sAppSrvAfter", + T.AUTH_ONLY "nAuthOnly", + DECODE(T.AUTH_ONLY, NAUTH_ONLY_NO, SAUTH_ONLY_NO, NAUTH_ONLY_YES, SAUTH_ONLY_YES) "sAuthOnly", + T.ERR_NTF_SIGN "nErrNtfSign", + DECODE(T.ERR_NTF_SIGN, NERR_NTF_SIGN_NO, SERR_NTF_SIGN_NO, NERR_NTF_SIGN_YES, SERR_NTF_SIGN_YES) "sErrNtfSign", + T.ERR_NTF_MAIL "sErrNtfMail" from EXSSERVICEFN T, EXSMSGTYPE M where T.RN in (select L.DOCUMENT from EXSRNLIST L where L.IDENT = NIDENT) @@ -1184,8 +1454,7 @@ create or replace package body PKG_EXS as NFLAG_SMART in number, -- (0 - , 1 - ) SEXSSERVICE in varchar2, -- SEXSSERVICEFN in varchar2 -- - ) - return number -- . + ) return number -- . is NEXSSERVICE PKG_STD.TREF; -- . NEXSSERVICEFN PKG_STD.TREF; -- . @@ -1202,6 +1471,36 @@ create or replace package body PKG_EXS as return NEXSSERVICEFN; end SERVICEFN_FIND_BY_SRVCODE; + /* */ + function SERVICEFN_CHECK_INCMPL_INQUEUE + ( + NEXSSERVICEFN in number -- . + ) return boolean -- (true - , false - ) + is + NCNT PKG_STD.TNUMBER; -- + begin + /* */ + select count(Q.RN) + into NCNT + from EXSQUEUE Q + where Q.EXSSERVICEFN = NEXSSERVICEFN + and Q.EXEC_STATE not in (NQUEUE_EXEC_STATE_OK, NQUEUE_EXEC_STATE_ERR); + /* ... */ + if (NCNT = 0) then + /* ... */ + return false; + else + /* - */ + return true; + end if; + exception + when others then + P_EXCEPTION(0, + ' (RN: %s) : %s', + TO_CHAR(NEXSSERVICEFN), + sqlerrm); + end SERVICEFN_CHECK_INCMPL_INQUEUE; + /* */ procedure LOG_GET ( @@ -1394,14 +1693,13 @@ create or replace package body PKG_EXS as /* */ function QUEUE_SRV_TYPE_SEND_EXEC_CHECK ( - NEXSQUEUE in number -- . - ) - return number -- (. NQUEUE_EXEC_*) + NEXSQUEUE in number -- . + ) return number -- (. NQUEUE_EXEC_*) is - REXSQUEUE EXSQUEUE%rowtype; -- - REXSSERVICE EXSSERVICE%rowtype; -- - REXSSERVICEFN EXSSERVICEFN%rowtype; -- - NRESULT number(17); -- + REXSQUEUE EXSQUEUE%rowtype; -- + REXSSERVICE EXSSERVICE%rowtype; -- + REXSSERVICEFN EXSSERVICEFN%rowtype; -- + NRESULT PKG_STD.TNUMBER; -- begin /* */ NRESULT := NQUEUE_EXEC_NO; @@ -1412,7 +1710,7 @@ create or replace package body PKG_EXS as REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => REXSQUEUE.EXSSERVICEFN); /* */ REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); - /* - , , */ + /* - , , , */ if ((REXSSERVICE.SRV_TYPE = NSRV_TYPE_SEND) and (REXSQUEUE.EXEC_STATE not in (NQUEUE_EXEC_STATE_OK, NQUEUE_EXEC_STATE_ERR, NQUEUE_EXEC_STATE_APP, NQUEUE_EXEC_STATE_DB)) and @@ -1421,7 +1719,9 @@ create or replace package body PKG_EXS as ((REXSSERVICEFN.RETRY_SCHEDULE = NRETRY_SCHEDULE_UNDEF) and (REXSQUEUE.EXEC_CNT = 0))) and (UTL_SCHED_CHECK_EXEC(DEXEC_DATE => REXSQUEUE.EXEC_DATE, NRETRY_SCHEDULE => REXSSERVICEFN.RETRY_SCHEDULE, - NRETRY_STEP => REXSSERVICEFN.RETRY_STEP))) then + NRETRY_STEP => REXSSERVICEFN.RETRY_STEP)) and + ((REXSSERVICEFN.AUTH_ONLY = NAUTH_ONLY_NO) or + ((REXSSERVICEFN.AUTH_ONLY = NAUTH_ONLY_YES) and (REXSSERVICE.IS_AUTH = NIS_AUTH_YES)))) then /* */ NRESULT := NQUEUE_EXEC_YES; end if; @@ -1461,7 +1761,7 @@ create or replace package body PKG_EXS as /* */ RNLIST_BASE_CLEAR(NIDENT => NIDENT); end QUEUE_SRV_TYPE_SEND_GET; - + /* */ procedure QUEUE_EXEC_STATE_SET ( @@ -1585,29 +1885,43 @@ create or replace package body PKG_EXS as /* */ QUEUE_GET(NFLAG_SMART => 0, NEXSQUEUE => NEXSQUEUE, RCQUEUE => RCQUEUE); end QUEUE_MSG_SET; - + /* */ procedure QUEUE_PUT ( - NEXSSERVICEFN in number, -- . - BMSG in blob, -- - NEXSQUEUE in number := null, -- . - NLNK_COMPANY in number := null, -- . - NLNK_DOCUMENT in number := null, -- . - SLNK_UNITCODE in varchar2 := null, -- - SOPTIONS in varchar2 := null, -- - NNEW_EXSQUEUE out number -- + NEXSSERVICEFN in number, -- . + BMSG in blob, -- + NEXSQUEUE in number := null, -- . + NLNK_COMPANY in number := null, -- . + NLNK_DOCUMENT in number := null, -- . + SLNK_UNITCODE in varchar2 := null, -- + SOPTIONS in varchar2 := null, -- + NNEW_EXSQUEUE out number -- ) is + REXSSERVICE EXSSERVICE%rowtype; -- + REXSSERVICEFN EXSSERVICEFN%rowtype; -- begin /* */ if (NEXSSERVICEFN is null) then - P_EXCEPTION(0, ' '); + P_EXCEPTION(0, ' .'); + end if; + /* */ + REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN); + /* */ + REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); + /* */ + if ((REXSSERVICE.SRV_TYPE = NSRV_TYPE_SEND) and (REXSSERVICEFN.AUTH_ONLY = NAUTH_ONLY_YES)) then + /* */ + if (SERVICE_IS_AUTH(NEXSSERVICE => REXSSERVICE.RN) = NIS_AUTH_NO) then + /* - */ + SERVICE_AUTH_PUT_INQUEUE(NEXSSERVICE => REXSSERVICE.RN); + end if; end if; /* */ P_EXSQUEUE_BASE_INSERT(DIN_DATE => sysdate, SIN_AUTHID => UTILIZER(), - NEXSSERVICEFN => NEXSSERVICEFN, + NEXSSERVICEFN => REXSSERVICEFN.RN, DEXEC_DATE => null, NEXEC_CNT => 0, NEXEC_STATE => NQUEUE_EXEC_STATE_INQUEUE, @@ -1635,7 +1949,7 @@ create or replace package body PKG_EXS as RCQUEUE out sys_refcursor -- ) is - NRN EXSQUEUE.RN%type; -- . + NRN EXSQUEUE.RN%type; -- . begin /* */ QUEUE_PUT(NEXSSERVICEFN => NEXSSERVICEFN, @@ -1664,7 +1978,7 @@ create or replace package body PKG_EXS as NNEW_EXSQUEUE out number -- ) is - NEXSSERVICEFN PKG_STD.TREF; -- . + NEXSSERVICEFN PKG_STD.TREF; -- . begin /* */ if (SEXSSERVICE is null) then @@ -1702,7 +2016,7 @@ create or replace package body PKG_EXS as RCQUEUE out sys_refcursor -- ) is - NRN EXSQUEUE.RN%type; -- . + NRN EXSQUEUE.RN%type; -- . begin /* */ QUEUE_PUT(SEXSSERVICE => SEXSSERVICE, diff --git a/models/intf_db_connector_module.js b/models/intf_db_connector_module.js index 02da169..b16a0d2 100644 --- a/models/intf_db_connector_module.js +++ b/models/intf_db_connector_module.js @@ -64,6 +64,57 @@ exports.dbConnectorModule = new Schema({ required: "Не реализована функция получения списка функций сервиса (getServiceFunctions)" } }, + //Получение контекста сервиса + getServiceContext: { + use: { validateAsyncFunctionType }, + required: true, + message: { + validateAsyncFunctionType: + "Функция получения контекста сервиса (getServiceContext) имеет неверный формат (ожидалось - AsyncFunction)", + required: "Не реализована функция получения контекста сервиса (getServiceContext)" + } + }, + //Установка контекста сервиса + setServiceContext: { + use: { validateAsyncFunctionType }, + required: true, + message: { + validateAsyncFunctionType: + "Функция установки контекста сервиса (setServiceContext) имеет неверный формат (ожидалось - AsyncFunction)", + required: "Не реализована функция установки контекста сервиса (setServiceContext)" + } + }, + //Очистка контекста сервиса + clearServiceContext: { + use: { validateAsyncFunctionType }, + required: true, + message: { + validateAsyncFunctionType: + "Функция очистки контекста сервиса (clearServiceContext) имеет неверный формат (ожидалось - AsyncFunction)", + required: "Не реализована функция очистки контекста сервиса (clearServiceContext)" + } + }, + //Проверка атуентифицированности сервиса + isServiceAuth: { + use: { validateAsyncFunctionType }, + required: true, + message: { + validateAsyncFunctionType: + "Функция проверки атуентифицированности сервиса (isServiceAuth) имеет неверный формат (ожидалось - AsyncFunction)", + required: "Не реализована функция проверки атуентифицированности сервиса (isServiceAuth)" + } + }, + //Постановка в очередь задания на аутентификацию сервиса + putServiceAuthInQueue: { + use: { validateAsyncFunctionType }, + required: true, + message: { + validateAsyncFunctionType: + "Функция постановки в очередь задания на аутентификацию сервиса (putServiceAuthInQueue) имеет неверный формат (ожидалось - AsyncFunction)", + required: + "Не реализована функция постановки в очередь задания на аутентификацию сервиса (putServiceAuthInQueue)" + } + }, //Протоколирование работы сервиса log: { use: { validateAsyncFunctionType }, diff --git a/models/obj_service.js b/models/obj_service.js index 1f6a3e1..afb8c0a 100644 --- a/models/obj_service.js +++ b/models/obj_service.js @@ -27,6 +27,12 @@ const NUNAVLBL_NTF_SIGN_YES = 1; //Оповещать о простое const SUNAVLBL_NTF_SIGN_NO = "UNAVLBL_NTF_NO"; //Не оповещать о простое (строковый код) const SUNAVLBL_NTF_SIGN_YES = "UNAVLBL_NTF_YES"; //Оповещать о простое (строковый код) +//Признак аутентифицированности сервиса +const NIS_AUTH_YES = 1; //Аутентифицирован +const NIS_AUTH_NO = 0; //Неаутентифицирован +const SIS_AUTH_YES = "IS_AUTH_YES"; //Аутентифицирован (строковый код) +const SIS_AUTH_NO = "IS_AUTH_NO"; //Неаутентифицирован (строковый код) + //------------- // Тело модуля //------------- @@ -49,8 +55,12 @@ exports.NUNAVLBL_NTF_SIGN_NO = NUNAVLBL_NTF_SIGN_NO; exports.NUNAVLBL_NTF_SIGN_YES = NUNAVLBL_NTF_SIGN_YES; exports.SUNAVLBL_NTF_SIGN_NO = SUNAVLBL_NTF_SIGN_NO; exports.SUNAVLBL_NTF_SIGN_YES = SUNAVLBL_NTF_SIGN_YES; +exports.NIS_AUTH_YES = NIS_AUTH_YES; +exports.NIS_AUTH_NO = NIS_AUTH_NO; +exports.SIS_AUTH_YES = SIS_AUTH_YES; +exports.SIS_AUTH_NO = SIS_AUTH_NO; -//Схема валидации +//Схема валидации сервиса exports.Service = new Schema({ //Идентификатор сервиса nId: { @@ -191,3 +201,67 @@ exports.Service = new Schema({ } } }); + +//Схема валидации контекста сервиса +exports.ServiceCtx = new Schema({ + //Идентификатор сервиса + nId: { + type: Number, + required: true, + message: { + type: "Идентификатор сервиса (nId) имеет некорректный тип данных (ожидалось - Number)", + required: "Не указан идентификатор сервиса (nId)" + } + }, + //Контекст + sCtx: { + type: String, + required: false, + message: { + type: "Контектс сервиса (sCtx) имеет некорректный тип данных (ожидалось - String)", + required: "Не указан контекст сервиса (sCtx)" + } + }, + //Дата истечения контекста + dCtxExp: { + type: Date, + required: false, + message: { + type: "Дата истечения контекста (dCtxExp) имеет некорректный тип данных (ожидалось - Date)", + required: "Не указана дата истечения контекста (dCtxExp)" + } + }, + //Дата истечения контекста (строковое представление) + sCtxExp: { + type: String, + required: false, + message: { + type: + "Строковое представление даты истечения контекста (sCtxExp) имеет некорректный тип данных (ожидалось - String)", + required: "Не указано строковое представление даты истечения контекста (sCtxExp)" + } + }, + //Признак аутентицированности сервиса + nIsAuth: { + type: Number, + enum: [NIS_AUTH_YES, NIS_AUTH_NO], + required: true, + message: { + type: "Признака аутентицированности сервиса (nIsAuth) имеет некорректный тип данных (ожидалось - Number)", + enum: "Значение признака аутентицированности сервиса (nIsAuth) не поддерживается", + required: "Не указан признак аутентицированности сервиса (nIsAuth)" + } + }, + //Признак аутентицированности сервиса (строковый код) + sIsAuth: { + type: String, + enum: [SIS_AUTH_YES, SIS_AUTH_NO], + required: true, + message: { + type: + "Строковый код признака аутентицированности сервиса (sIsAuth) имеет некорректный тип данных (ожидалось - String)", + enum: "Значение строкового кода признака аутентицированности сервиса (sIsAuth) не поддерживается", + required: "Не указан строковый код признака аутентицированности сервиса (sIsAuth)" + } + } +}); diff --git a/models/obj_service_function.js b/models/obj_service_function.js index 08c88c1..6d66d68 100644 --- a/models/obj_service_function.js +++ b/models/obj_service_function.js @@ -8,6 +8,7 @@ //---------------------- const Schema = require("validate"); //Схемы валидации +const { validateMailList } = require("./common"); //Общие объекты валидации моделей данных //---------- // Константы @@ -43,6 +44,18 @@ const SRETRY_SCHEDULE_DAY = "DAY"; //Сутки (строковый код) const SRETRY_SCHEDULE_WEEK = "WEEK"; //Неделя (строковый код) const SRETRY_SCHEDULE_MONTH = "MONTH"; //Месяц (строковый код) +//Признак необходимости аутентифицированности сервиса для исполнения функции +const NAUTH_ONLY_YES = 1; //Требуется аутентификация +const NAUTH_ONLY_NO = 0; //Аутентификация не требуется +const SAUTH_ONLY_YES = "AUTH_ONLY_YES"; //Требуется аутентификация (строковый код) +const SAUTH_ONLY_NO = "AUTH_ONLY_NO"; //Аутентификация не требуется (строковый код) + +//Признак оповещения об ошибке исполнения сообщения очереди для функции обработки +const NERR_NTF_SIGN_NO = 0; //Не оповещать об ошибке исполнения +const NERR_NTF_SIGN_YES = 1; //Оповещать об ошибке исполнения +const SERR_NTF_SIGN_NO = "ERR_NTF_SIGN_NO"; //Не оповещать об ошибке исполнения (строковый код) +const SERR_NTF_SIGN_YES = "ERR_NTF_SIGN_YES"; //Оповещать об ошибке исполнения (строковый код) + //------------- // Тело модуля //------------- @@ -56,6 +69,11 @@ const validateAppSrvFn = val => { return true; }; +//Валидация списка адресов E-Mail для оповещения об ошибке обработки сообщения очереди +const validateErrNtfMail = val => { + return validateMailList(val); +}; + //------------------ // Интерфейс модуля //------------------ @@ -85,6 +103,14 @@ exports.SRETRY_SCHEDULE_HOUR = SRETRY_SCHEDULE_HOUR; exports.SRETRY_SCHEDULE_DAY = SRETRY_SCHEDULE_DAY; exports.SRETRY_SCHEDULE_WEEK = SRETRY_SCHEDULE_WEEK; exports.SRETRY_SCHEDULE_MONTH = SRETRY_SCHEDULE_MONTH; +exports.NAUTH_ONLY_YES = NAUTH_ONLY_YES; +exports.NAUTH_ONLY_NO = NAUTH_ONLY_NO; +exports.SAUTH_ONLY_YES = SAUTH_ONLY_YES; +exports.SAUTH_ONLY_NO = SAUTH_ONLY_NO; +exports.NERR_NTF_SIGN_NO = NERR_NTF_SIGN_NO; +exports.NERR_NTF_SIGN_YES = NERR_NTF_SIGN_YES; +exports.SERR_NTF_SIGN_NO = SERR_NTF_SIGN_NO; +exports.SERR_NTF_SIGN_YES = SERR_NTF_SIGN_YES; //Схема валидации функции сервиса exports.ServiceFunction = new Schema({ @@ -270,5 +296,74 @@ exports.ServiceFunction = new Schema({ validateAppSrvFn: "Обработчик сообщения 'после' на строне сервера приложений для функции сервиса (sAppSrvBefore) имеет некорректный формат, ожидалось: <МОДУЛЬ>.js/<ФУНКЦИЯ>" } + }, + //Признак необходимости аутентификации для исполнения функции сервсиа обмена + nAuthOnly: { + type: Number, + enum: [NAUTH_ONLY_NO, NAUTH_ONLY_YES], + required: true, + message: { + type: + "Признак необходимости аутентификации для исполнения функции сервсиа обмена (nAuthOnly) имеет некорректный тип данных (ожидалось - Number)", + enum: + "Значение признака необходимости аутентификации для исполнения функции сервсиа обмена (nAuthOnly) не поддерживается", + required: "Не указан признак необходимости аутентификации для исполнения функции сервсиа обмена (nAuthOnly)" + } + }, + //Признак необходимости аутентификации для исполнения функции сервсиа обмена (строковый код) + sAuthOnly: { + type: String, + enum: [SAUTH_ONLY_NO, SAUTH_ONLY_YES], + required: true, + message: { + type: + "Строковый код признака необходимости аутентификации для исполнения функции сервсиа обмена (sAuthOnly) имеет некорректный тип данных (ожидалось - String)", + enum: + "Значение строкового кода признака необходимости аутентификации для исполнения функции сервсиа обмена (sAuthOnly) не поддерживается", + required: + "Не указан строковый код признака необходимости аутентификации для исполнения функции сервсиа обмена (sAuthOnly)" + } + }, + //Признак оповещения об ошибке исполнения сообщения очереди для функции обработки + nErrNtfSign: { + type: Number, + enum: [NERR_NTF_SIGN_NO, NERR_NTF_SIGN_YES], + required: true, + message: { + type: + "Признак оповещения об ошибке исполнения сообщения очереди для функции обработки (nErrNtfSign) имеет некорректный тип данных (ожидалось - Number)", + enum: + "Значение признака оповещения об ошибке исполнения сообщения очереди для функции обработки (nErrNtfSign) не поддерживается", + required: + "Не указан признак оповещения об ошибке исполнения сообщения очереди для функции обработки (nErrNtfSign)" + } + }, + //Признак оповещения об ошибке исполнения сообщения очереди для функции обработки (строковый код) + sErrNtfSign: { + type: String, + enum: [SERR_NTF_SIGN_NO, SERR_NTF_SIGN_YES], + required: true, + message: { + type: + "Строковый код признака оповещения об ошибке исполнения сообщения очереди для функции обработки (sErrNtfSign) имеет некорректный тип данных (ожидалось - String)", + enum: + "Значение строкового кода признака оповещения об ошибке исполнения сообщения очереди для функции обработки (sErrNtfSign) не поддерживается", + required: + "Не указан строковый код признака оповещения об ошибке исполнения сообщения очереди для функции обработки (sErrNtfSign)" + } + }, + //Список адресов E-Mail для оповещения об ошибке исполнения сообщения очереди для функции обработки + sErrNtfMail: { + type: String, + required: false, + use: { validateErrNtfMail }, + message: { + type: + "Список адресов E-Mail для оповещения об ошибке исполнения сообщения очереди для функции обработки (sErrNtfMail) имеет некорректный тип данных (ожидалось - String)", + required: + "Не указан список адресов E-Mail для оповещения об ошибке исполнения сообщения очереди для функции обработки (sErrNtfMail)", + validateErrNtfMail: + "Неверный формат списка адресов E-Mail для оповещения об ошибке исполнения сообщения очереди для функции обработки (sErrNtfMail), для указания нескольких адресов следует использовать запятую в качестве разделителя (без пробелов)" + } } }); diff --git a/models/prms_db_connector.js b/models/prms_db_connector.js index 7bfb9f3..c45e77f 100644 --- a/models/prms_db_connector.js +++ b/models/prms_db_connector.js @@ -78,6 +78,89 @@ exports.getServiceFunctions = new Schema({ } }); +//Схема валидации параметров функции получения контекста сервиса +exports.getServiceContext = new Schema({ + //Идентификатор сервиса + nServiceId: { + type: Number, + required: true, + message: { + type: path => `Идентификатор сервиса (${path}) имеет некорректный тип данных (ожидалось - Number)`, + required: path => `Не указан идентификатор сервиса (${path})` + } + } +}); + +//Схема валидации параметров функции установки контектса сервиса +exports.setServiceContext = new Schema({ + //Идентификатор сервиса + nServiceId: { + type: Number, + required: true, + message: { + type: path => `Идентификатор сервиса (${path}) имеет некорректный тип данных (ожидалось - Number)`, + required: path => `Не указан идентификатор сервиса (${path})` + } + }, + //Контекст сервиса + sCtx: { + type: String, + required: true, + message: { + type: path => `Контекст сервиса (${path}) имеет некорректный тип данных (ожидалось - String)`, + required: path => `Не указан контекст сервиса (${path})` + } + }, + //Дата истечения контекста сервиса + dCtxExp: { + type: Date, + required: false, + message: { + type: path => `Дата истечения контекст сервиса (${path}) имеет некорректный тип данных (ожидалось - Date)`, + required: path => `Не указана дата истечения контекста сервиса (${path})` + } + } +}); + +//Схема валидации параметров функции очистки контекста сервиса +exports.clearServiceContext = new Schema({ + //Идентификатор сервиса + nServiceId: { + type: Number, + required: true, + message: { + type: path => `Идентификатор сервиса (${path}) имеет некорректный тип данных (ожидалось - Number)`, + required: path => `Не указан идентификатор сервиса (${path})` + } + } +}); + +//Схема валидации параметров функции проверки аутентифицированности сервиса +exports.isServiceAuth = new Schema({ + //Идентификатор сервиса + nServiceId: { + type: Number, + required: true, + message: { + type: path => `Идентификатор сервиса (${path}) имеет некорректный тип данных (ожидалось - Number)`, + required: path => `Не указан идентификатор сервиса (${path})` + } + } +}); + +//Схема валидации параметров функции постановки в очередь задания на аутентификацию сервиса +exports.putServiceAuthInQueue = new Schema({ + //Идентификатор сервиса + nServiceId: { + type: Number, + required: true, + message: { + type: path => `Идентификатор сервиса (${path}) имеет некорректный тип данных (ожидалось - Number)`, + required: path => `Не указан идентификатор сервиса (${path})` + } + } +}); + //Схема валидации параметров функции записи в журнал работы сервиса exports.putLog = new Schema({ //Тип сообщения журнала работы сервиса diff --git a/modules/parus_oracle_db.js b/modules/parus_oracle_db.js index 0f61fff..7654b6e 100644 --- a/modules/parus_oracle_db.js +++ b/modules/parus_oracle_db.js @@ -85,6 +85,73 @@ const getServiceFunctions = async prms => { } }; +//Получение контекста сервиса +const getServiceContext = async prms => { + try { + let res = await prms.connection.execute( + "BEGIN PKG_EXS.SERVICE_CTX_GET(NFLAG_SMART => 0, NEXSSERVICE => :NEXSSERVICE, RCSERVICE_CTX => :RCSERVICE_CTX); END;", + { NEXSSERVICE: prms.nServiceId, RCSERVICE_CTX: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, + { outFormat: oracledb.OBJECT } + ); + let rows = await readCursorData(res.outBinds.RCSERVICE_CTX); + return rows[0]; + } catch (e) { + throw new Error(e.message); + } +}; + +//Установка контекста сервиса +const setServiceContext = async prms => { + try { + await prms.connection.execute( + "BEGIN PKG_EXS.SERVICE_CTX_SET(NEXSSERVICE => :NEXSSERVICE, SCTX => :SCTX, DCTX_EXP => :DCTX_EXP); END;", + { NEXSSERVICE: prms.nServiceId, SCTX: prms.sCtx, DCTX_EXP: prms.dCtxExp }, + { autoCommit: true } + ); + } catch (e) { + throw new Error(e.message); + } +}; + +//Очистка контекста сервиса +const clearServiceContext = async prms => { + try { + await prms.connection.execute( + "BEGIN PKG_EXS.SERVICE_CTX_CLEAR(NEXSSERVICE => :NEXSSERVICE); END;", + { NEXSSERVICE: prms.nServiceId }, + { autoCommit: true } + ); + } catch (e) { + throw new Error(e.message); + } +}; + +//Проверка атуентифицированности сервиса +const isServiceAuth = async prms => { + try { + let res = await prms.connection.execute( + "BEGIN :RET := PKG_EXS.SERVICE_IS_AUTH(NEXSSERVICE => :NEXSSERVICE); END;", + { NEXSSERVICE: prms.nServiceId, RET: { dir: oracledb.BIND_OUT, type: oracledb.NUMBER } } + ); + return res.outBinds.RET; + } catch (e) { + throw new Error(e.message); + } +}; + +//Постановка в очередь задания на аутентификацию сервиса +const putServiceAuthInQueue = async prms => { + try { + await prms.connection.execute( + "BEGIN PKG_EXS.SERVICE_AUTH_PUT_INQUEUE(NEXSSERVICE => :NEXSSERVICE); END;", + { NEXSSERVICE: prms.nServiceId }, + { autoCommit: true } + ); + } catch (e) { + throw new Error(e.message); + } +}; + //Запись в протокол работы const log = async prms => { try { @@ -296,6 +363,11 @@ exports.connect = connect; exports.disconnect = disconnect; exports.getServices = getServices; exports.getServiceFunctions = getServiceFunctions; +exports.getServiceContext = getServiceContext; +exports.setServiceContext = setServiceContext; +exports.clearServiceContext = clearServiceContext; +exports.isServiceAuth = isServiceAuth; +exports.putServiceAuthInQueue = putServiceAuthInQueue; exports.log = log; exports.getQueue = getQueue; exports.putQueue = putQueue;