this.name = hash(getCurrentTemplatePath());
//variables.framework = structNew(); //
variables.framework.debugKey = "debug";
variables.framework.reloadKey = "reload";
variables.framework.reloadPassword = "true";
variables.framework.reloadOnEveryRequest = true;
variables.framework.serializer = "taffy.core.nativeJsonSerializer";
//variables.framework.serializer = "JsonUtilSerializer";
variables.framework.dashboardKey = "dashboard";
variables.framework.disableDashboard = false;
variables.framework.unhandledPaths = "/flex2gateway";
variables.framework.allowCrossDomain = true; // соответствующие заголовки, включая Access-Control-Allow-Origin выставляются только при наличии заголовка origin в реквесте
//variables.framework.allowCrossDomain = ""; // перепишем явно, возвращая Origin
//variables.framework.docs={};
variables.framework.docs.APIName="svc-api";
variables.framework.docs.APIVersion="0.234"; /*$ git config --global --unset user.password*/
variables.framework.globalHeaders = structNew();
variables.framework.globalHeaders["Access-Control-Expose-Headers"] = "Location";
variables.framework.globalHeaders["Access-Control-Allow-Credentials"] = "true";
variables.framework.globalHeaders["X-Application-Version"] = variables.framework.docs.APIVersion;
//variables.framework.globalHeaders["Access-Control-Allow-Origin"] = "*";
request.UNDEFINED_USR_ID=-1;
request.ANONYMOUS_USR_ID=2;
request.GUEST_USR_ID=3;
request.USER_AGENT="#variables.framework.docs.APIName# #variables.framework.docs.APIVersion# stand:#this.getStand()#";
////////////////////////////////////////////////////////
request.ORCHESTRATOR_AUTH = createObject("java", "java.lang.System").getEnv("ORCHESTRATOR_AUTH");
if (isNull(request.ORCHESTRATOR_AUTH)) {
request.ORCHESTRATOR_AUTH = "Basic ...no data";//*** времянка, дубль из deck/Application.cfm
}
//request.vault_login_url=createObject("java", "java.lang.System").getEnv("VAULT_LOGIN_URL");
request.vault_login_url="https://vault.lk.adl.nubes.ru/v1/auth/approle/login";
request.vault_role_id=createObject("java", "java.lang.System").getEnv("VAULT_ROLE_ID");
request.vault_secret_id=createObject("java", "java.lang.System").getEnv("VAULT_SECRET_ID");//*** тут в другом скоупе, не как deck, и вообще стоит ли это делать в псевдоконструкторе
//*** почему-то scope this ведет себя совершенно не так, как request и variables
// в нем, когда переменная получает значение Empty:null, можно выполнить writedump, а в других получаем ошибку, что такой переменной нет
request.auth_header="";
//request.locateIamService=locateIamService; //for possible debug
//request.IAM_SERVICE_URL=this.iamServiceUrl; // так не работает!
select value as stand from config
where name='STAND'
select value as stand from config
where name='STAND'
--->
function onTaffyRequest(verb, cfc, requestArguments, mimeExt, headers){
/* https://docs.taffy.io/#/3.5.0 */
/*
//allow white-listed requests through
if (cfc == "login"){
return true;
}
//otherwise require a device token
if (!structKeyExists(requestArguments, "deviceToken")){
return newRepresentation().noData().withStatus(401, "Authentication Required");
//and make sure it's valid
}else if (!validateToken(requestArguments.deviceToken)){
return newRepresentation().noData().withStatus(403, "Not Authorized");
}
//return representationOf(requestArguments);
//if a token is included, and valid, allow the request to continue
return true;
*/
////////////////////////////////////////////////
// самым грубым образом получаем данные от IDP, не обрабатывая исключения
//if (variables.framework.allowCrossDomain EQ "") {
//corsHeaders(); // *** нужно, чтобы variables.framework.allowCrossDomain="" иначе задвоятся заголовки
//}
//if (UCase(arguments.verb) EQ 'OPTIONS') return newRepresentation().noData().withStatus("204","No Data").withHeaders({"Content-Type":"application/json;charset=utf-8"});
request.stand=this.getStand();
request.iam_service_url=this.iamServiceUrl;
if (uCase(arguments.verb) EQ 'OPTIONS') return true;
if (lCase(arguments.cfc) EQ 'err') return true;
if (lCase(arguments.cfc) EQ 'throw') return true;
if (structKeyExists(headers,"Authorization")) {
request.auth_header=headers.Authorization;
} else {
return representationOf("Authorization header expected").withStatus(401);
}
var result="";
try {
var authUrl = "#this.iamServiceUrl#/auth/user";
var httpService = new http(method = "GET", charset = "utf-8", url = #authUrl#, timeout="5");
httpService.addParam(type = "HEADER", name = "Accept", value = "application/json");
httpService.addParam(type = "HEADER", name = "Authorization", value = "#request.auth_header#"); //passthrough
//writedump(authUrl);abort;
var resp = httpService.send();
//if (resp.status_code NEQ 200) throw("IDP response not OK");
//writedump(resp);abort;
var prefix = resp.getPrefix();
if (prefix.status_code NEQ 200) {
//writedump(authUrl);
//writedump(resp);
var iamStatusCode = (isValid("integer", prefix.status_code)) ? val(prefix.status_code) : 500;
return representationOf( {"IAM URL"=#authUrl#, "idpResponse"=resp} ).withStatus(iamStatusCode);
//abort;
//throw("IDP response not OK");
}
result = prefix.filecontent;
//writedump(result);abort;
} catch (e) {
return representationOf( {"exception"=e, "idpResponse"=result} ).withStatus(200);
}
//writeDump(result); abort;
try {
var idpUserData=deserializeJson(result);
"arguments.requestArguments.companyUid"=idpUserData.userInfo.companyId;//GUID!
"arguments.requestArguments.usrUid"=idpUserData.userInfo.contactId;//userId; //GUID!
var usrCustomerInfo=getUsrCustomerInfo(idpUserData.userInfo.contactId, idpUserData.userInfo.companyId);
} catch (e) {
return representationOf( {"exception.Message"=e.Message, "exception.Detail"=e.Detail, "idpResponse"=result} ).withStatus(422);
}
//dump(idpUserData);dump(usrCustomerInfo);abort;
if (lCase(arguments.cfc) EQ 'user') {
if (structIsEmpty(usrCustomerInfo)) return representationOf("User information not found").withStatus(404);
}
if (lCase(arguments.cfc) EQ 'notification_ls') { //*** костыль: для нотификаций можно адресоваться к пользователю без контракта
if (structIsEmpty(usrCustomerInfo)) {
"arguments.requestArguments.usrId"=-1; //Integer!
"arguments.requestArguments.contragentId"=-1; //Integer
"arguments.requestArguments.contractId"=-1; //Integer
"arguments.requestArguments.specificationId"=-1; //Integer
"arguments.requestArguments.isImpersonated"=false;
"arguments.requestArguments.clientID"="";
"arguments.requestArguments.login"="";
return true;
}
}
if (structIsEmpty(usrCustomerInfo)) return representationOf("Cannot find default specification for current user #result#").withStatus(422); //это создает довольно много лишних движений при отладке
"arguments.requestArguments.usrId"=usrCustomerInfo.usrId; //Integer
"arguments.requestArguments.contragentId"=usrCustomerInfo.contragentId; //Integer
"arguments.requestArguments.contractId"=usrCustomerInfo.contractId; //Integer
"arguments.requestArguments.specificationId"=usrCustomerInfo.specificationId; //Integer
try {
"arguments.requestArguments.isImpersonated"=idpUserData.impersonation.is_impersonated;
} catch (e) {
"arguments.requestArguments.isImpersonated"=false; // так себе решение, надо было бы NULL
}
try {
"arguments.requestArguments.clientID"=idpUserData.userInfo.clientID;
} catch (e) {
"arguments.requestArguments.clientID"="";
}
try {
"arguments.requestArguments.login"=idpUserData.userInfo.login;
} catch (e) {
"arguments.requestArguments.login"="";
}
return true;
}
select usr_id from usr where login=
#cfcatch.message# : #cfcatch.detail#
#cfcatch.message# : #cfcatch.detail#
select z.contragent_id, c.contract_id, s.specification_id
from contragent z
join contract c on (z.contragent_id=c.contragent_id)
join specification s on (c.contract_id=s.contract_id)
where z.external_uid=
order by s.specification_id desc
limit 1;
select z.contragent_id
from contragent z
where z.external_uid=
select z.contragent_id, c.contract_id
from contragent z
join contract c on (z.contragent_id=c.contragent_id)
where z.external_uid=
select u.usr_id, u.contragent_id, k.contragent_id as c_contragent_id
from usr u
left outer join contragent k on (u.contragent_id=k.contragent_id)
where u.idp_usr_uid=
limit 1;
#local.resultSerialized#
Request Details: