cleanup: strip remaining comment noise
This commit is contained in:
@@ -135,6 +135,16 @@
|
||||
Ожидаемый результат:
|
||||
- единообразный русскоязычный комментарийный слой там, где комментарии реально остаются
|
||||
|
||||
### Этап E. Дочистка явных хвостов
|
||||
|
||||
Сделать:
|
||||
- удалить закомментированный `onRequest` и старые Taffy-заготовки из `v1/Application.cfc`
|
||||
- убрать остатки debug-комментариев и лишних пояснений из `v1/resources/instance_operation_run.cfc`
|
||||
- перепроверить, что логика не изменилась
|
||||
|
||||
Ожидаемый результат:
|
||||
- source-файлы без явного мусора и без затронутого runtime
|
||||
|
||||
### Этап E. Сводный документ
|
||||
|
||||
Сделать:
|
||||
@@ -152,6 +162,21 @@
|
||||
- подготовить список вопросов по неоднозначным местам
|
||||
- отдельно указать, какие решения были приняты по умолчанию без уточнения заказчика
|
||||
|
||||
### Этап G. Дочистка remaining source-файлов
|
||||
|
||||
Сделать:
|
||||
- убрать декоративные и старые комментарии из оставшихся прикладных `v1/*` файлов
|
||||
- отдельно дочистить `v1/Application.cfc` от закомментированного кода и явного мусора
|
||||
- проверить, что `git diff --check` остаётся чистым
|
||||
|
||||
Ожидаемый результат:
|
||||
- текущий набор source-файлов без явных comment-hash остатков и без сломанной логики
|
||||
|
||||
Результат:
|
||||
- большая часть remaining source-файлов очищена от декоративных комментариев
|
||||
- `v1/Application.cfc` очищен от закомментированного кода и старых debug-хвостов
|
||||
- `git diff --check` после правок остаётся чистым
|
||||
|
||||
## Принятые допущения на текущий момент
|
||||
|
||||
1. Работу нужно вести в отдельной ветке, а не в `dev`.
|
||||
|
||||
+14
-132
@@ -68,7 +68,6 @@
|
||||
|
||||
|
||||
<cffunction name="rethrow" returntype="void">
|
||||
<!--- https://www.raymondcamden.com/2004/03/09/3089633C-9FA0-606B-3F540AE9642A795F --->
|
||||
<cftry>
|
||||
<cfcatch>
|
||||
<cfrethrow/>
|
||||
@@ -148,50 +147,10 @@
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
</cffunction>
|
||||
|
||||
<!--- <cffunction name="onRequest">
|
||||
<cfargument name="template" type="string" required="true"/>
|
||||
<cfset request.startTickCount=getTickCount()/>
|
||||
<!---<cfheader name="Access-Control-Allow-Origin" value="*"/>--->
|
||||
<cfreturn super.onRequest(template) />
|
||||
</cffunction> --->
|
||||
|
||||
|
||||
|
||||
<cfscript>
|
||||
|
||||
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;
|
||||
|
||||
@@ -210,49 +169,39 @@
|
||||
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;
|
||||
httpService.addParam(type = "HEADER", name = "Authorization", value = "#request.auth_header#");
|
||||
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!
|
||||
"arguments.requestArguments.companyUid"=idpUserData.userInfo.companyId;
|
||||
"arguments.requestArguments.usrUid"=idpUserData.userInfo.contactId;
|
||||
|
||||
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 (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.usrId"=-1;
|
||||
"arguments.requestArguments.contragentId"=-1;
|
||||
"arguments.requestArguments.contractId"=-1;
|
||||
"arguments.requestArguments.specificationId"=-1;
|
||||
"arguments.requestArguments.isImpersonated"=false;
|
||||
"arguments.requestArguments.clientID"="";
|
||||
"arguments.requestArguments.login"="";
|
||||
@@ -261,17 +210,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (structIsEmpty(usrCustomerInfo)) return representationOf("Cannot find default specification for current user #result#").withStatus(422); //это создает довольно много лишних движений при отладке
|
||||
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
|
||||
"arguments.requestArguments.usrId"=usrCustomerInfo.usrId;
|
||||
"arguments.requestArguments.contragentId"=usrCustomerInfo.contragentId;
|
||||
"arguments.requestArguments.contractId"=usrCustomerInfo.contractId;
|
||||
"arguments.requestArguments.specificationId"=usrCustomerInfo.specificationId;
|
||||
|
||||
try {
|
||||
"arguments.requestArguments.isImpersonated"=idpUserData.impersonation.is_impersonated;
|
||||
} catch (e) {
|
||||
"arguments.requestArguments.isImpersonated"=false; // так себе решение, надо было бы NULL
|
||||
"arguments.requestArguments.isImpersonated"=false;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -300,7 +249,6 @@
|
||||
|
||||
|
||||
<cffunction name="checkAuth">
|
||||
<!---https://www.sjoerdlangkemper.nl/2018/09/12/authorization-header-and-cors/--->
|
||||
<cfset var jwtHelper=CreateObject("component","lib.jwt").init()/>
|
||||
<cfset var headers=#GetHttpRequestData().headers#/>
|
||||
<cftry>
|
||||
@@ -308,7 +256,6 @@
|
||||
<cfset var token=jwtHelper.decode(token=rawToken, key=request.config.IDP_certificate.keys[1], algorithms='RS256')/>
|
||||
|
||||
<cfset var login=token.preferred_username/>
|
||||
<!---отрезаем первичный домен --->
|
||||
<cfset login=ReplaceNoCase(login,"#request.config.auth_domain_suffix#","")/>
|
||||
<cfquery name="local.qUsr">
|
||||
select usr_id from usr where login=<cfqueryparam cfsqltype="cf_sql_varchar" value="#login#"/>
|
||||
@@ -340,7 +287,6 @@
|
||||
|
||||
|
||||
<cffunction name="getUsrCustomerInfo">
|
||||
<!--- Может быть имперсонирована компания, а может контакт,
|
||||
при этом если имперсонируется компания, то спецификацию и контракт нужно брать по компании
|
||||
Кстати, зачем нужен вообще юзер, если компания всегда доступна, а вся информация висит на ней
|
||||
Для того, чтобы разрешить ключ в целочисленный ключ CMDB--->
|
||||
@@ -348,18 +294,13 @@
|
||||
<cfargument name="contragentUid"/>
|
||||
|
||||
<cfif !isValid('guid',arguments.usrUid)>
|
||||
<cfthrow message="Invalid user uuid" detail="uuid=(#arguments.usrUid#) is not a valid UUID"/><!--- тут спорно, можно было бы и 400 и 500, но исключения из этой функции не дифференцированы по типам --->
|
||||
</cfif>
|
||||
<cfif !isValid('guid',arguments.contragentUid)>
|
||||
<cfthrow message="Invalid contragent uuid" detail="uuid=(#arguments.contragentUid#) is not a valid UUID"/>
|
||||
</cfif>
|
||||
|
||||
<!--- глупейшее определение спецификации по умолчанию (надо переделать, чтобы создавалась, или вообще просто записывать факты без спеки). Но помним, что при постановке на тестирование цены еше не фиксированы --->
|
||||
<!--- заметим, что у нас контрагент может быть определен параллельно, от IDP --->
|
||||
<cfset local={}/>
|
||||
|
||||
<!--- Во избежании потери времени при отладке временно сделаем создание дефолтового контракта и спецификации, если их нет --->
|
||||
<!--- *** хватается первый попавшийся контракт и спецификация --->
|
||||
|
||||
<cfquery name="local.qGetContragentInfo">
|
||||
select z.contragent_id, c.contract_id, s.specification_id
|
||||
@@ -372,7 +313,6 @@
|
||||
</cfquery>
|
||||
|
||||
<cfif local.qGetContragentInfo.recordCount EQ 0>
|
||||
<!--- диагностика (тут можно не переживать за производительность, история редкая) --->
|
||||
<cfquery name="local.qGetContragent">
|
||||
select z.contragent_id
|
||||
from contragent z
|
||||
@@ -414,7 +354,6 @@
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- <cfdump var=#local.qGetCustomerInfo#/><cfabort/> --->
|
||||
<cfreturn {
|
||||
"usrId"=#local.qGetUserInfo.usr_id#,
|
||||
"contragentId"=#local.qGetContragentInfo.contragent_id#,
|
||||
@@ -426,7 +365,6 @@
|
||||
|
||||
|
||||
<cffunction name="corsHeaders">
|
||||
<!--- *** фрагмент взят из taffy/core/api.cfc и немного переписан --->
|
||||
<cfset var _taffyRequest=request._taffyRequest/>
|
||||
<cfset local={}/>
|
||||
|
||||
@@ -441,11 +379,9 @@
|
||||
<cfheader name="Access-Control-Allow-Origin" value="#_taffyRequest.headers.origin#" />
|
||||
|
||||
<cfheader name="Access-Control-Allow-Methods" value="#local.allowVerbs#" />
|
||||
<!--- Why do we parrot back these headers? See: https://github.com/atuttle/Taffy/issues/144 --->
|
||||
<cfif not structKeyExists(_taffyRequest.headers, "Access-Control-Request-Headers")>
|
||||
<cfheader name="Access-Control-Allow-Headers" value="Origin, Authorization, X-CSRF-Token, X-Requested-With, Content-Type, X-HTTP-Method-Override, Accept, Referrer, User-Agent" />
|
||||
<cfelse>
|
||||
<!--- parrot back all of the request headers to allow the request to continue (can we improve on this?) --->
|
||||
<cfset local.allowedHeaders = {} />
|
||||
<cfloop list="Origin,Authorization,X-CSRF-Token,X-Requested-With,Content-Type,X-HTTP-Method-Override,Accept,Referrer,User-Agent" index="local.h">
|
||||
<cfset local.allowedHeaders[local.h] = 1 />
|
||||
@@ -459,14 +395,9 @@
|
||||
</cfif>
|
||||
</cffunction>
|
||||
|
||||
<!--- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: --->
|
||||
<!--- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: --->
|
||||
|
||||
<!--- Overriding TAFFY short-circuit logic (taffy/core/api.cfc) --->
|
||||
<cffunction name="onRequest" output="true" returntype="boolean">
|
||||
<cfargument name="targetPage" type="string" required="true" />
|
||||
|
||||
<cfset request.startTickCount=getTickCount()/><!--- *** --->
|
||||
|
||||
<cfset var _taffyRequest = {} />
|
||||
<cfset var local = {} />
|
||||
@@ -478,12 +409,10 @@
|
||||
<cfset m = _taffyRequest.metrics />
|
||||
<cfset m.init = getTickCount() />
|
||||
|
||||
<!--- enable/disable debug output per settings --->
|
||||
<cfif not structKeyExists(url, application._taffy.settings.debugKey)>
|
||||
<cfsetting showdebugoutput="false" />
|
||||
</cfif>
|
||||
|
||||
<!--- display api dashboard if requested --->
|
||||
<cfif
|
||||
NOT structKeyExists(url,application._taffy.settings.endpointURLParam)
|
||||
AND NOT structKeyExists(form,application._taffy.settings.endpointURLParam)
|
||||
@@ -509,14 +438,12 @@
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<!--- get request details --->
|
||||
<cfset m.beforeParse = getTickCount() />
|
||||
<cfset local.parsed = parseRequest() />
|
||||
<cfset m.afterParse = getTickCount() />
|
||||
<cfset structAppend(_taffyRequest, local.parsed) />
|
||||
<cfset m.parseTime = m.afterParse - m.beforeParse />
|
||||
|
||||
<!--- CORS headers (so that CORS can pass even if the resource throws an exception) --->
|
||||
<cfset local.allowVerbs = uCase(structKeyList(_taffyRequest.matchDetails.methods)) />
|
||||
<cfif (application._taffy.settings.allowCrossDomain eq true or len(application._taffy.settings.allowCrossDomain) gt 0)
|
||||
AND listFindNoCase('PUT,PATCH,DELETE,OPTIONS',_taffyRequest.verb)
|
||||
@@ -525,14 +452,8 @@
|
||||
</cfif>
|
||||
<cfif structKeyExists(_taffyRequest.headers, "origin") AND (application._taffy.settings.allowCrossDomain eq true or len(application._taffy.settings.allowCrossDomain) gt 0)>
|
||||
<cfif application._taffy.settings.allowCrossDomain eq true>
|
||||
<!--- <cfheader name="Access-Control-Allow-Origin" value="*" /> ---><!--- *** dirty hack 2024-10-23 17:59:43--->
|
||||
<cfheader name="Access-Control-Allow-Origin" value="#_taffyRequest.headers.origin#" />
|
||||
<cfelse>
|
||||
<!---
|
||||
The Access-Control-Allow-Origin header can only have 1 value so we check to see if the Origin header is
|
||||
in the list of origins specified in the config setting and parrot back the Origin header if so.
|
||||
We also need to add the Access-Control-Allow-Credentials header and set it to true for those type requests
|
||||
--->
|
||||
<cfset local.domains = listToArray( application._taffy.settings.allowCrossDomain, ', ;' )>
|
||||
<cfif structKeyExists(_taffyRequest.headers, "origin")>
|
||||
<cfloop from="1" to="#arrayLen( local.domains )#" index="local.i">
|
||||
@@ -545,11 +466,9 @@
|
||||
</cfif>
|
||||
</cfif>
|
||||
<cfheader name="Access-Control-Allow-Methods" value="#local.allowVerbs#" />
|
||||
<!--- Why do we parrot back these headers? See: https://github.com/atuttle/Taffy/issues/144 --->
|
||||
<cfif not structKeyExists(_taffyRequest.headers, "Access-Control-Request-Headers")>
|
||||
<cfheader name="Access-Control-Allow-Headers" value="Origin, Authorization, X-CSRF-Token, X-Requested-With, Content-Type, X-HTTP-Method-Override, Accept, Referrer, User-Agent" />
|
||||
<cfelse>
|
||||
<!--- parrot back all of the request headers to allow the request to continue (can we improve on this?) --->
|
||||
<cfset local.allowedHeaders = {} />
|
||||
<cfloop list="Origin,Authorization,X-CSRF-Token,X-Requested-With,Content-Type,X-HTTP-Method-Override,Accept,Referrer,User-Agent" index="local.h">
|
||||
<cfset local.allowedHeaders[local.h] = 1 />
|
||||
@@ -562,14 +481,11 @@
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<!--- global headers --->
|
||||
<cfset addHeaders(getGlobalHeaders()) />
|
||||
|
||||
<!---
|
||||
Now we know everything we need to know to service the request. let's service it!
|
||||
--->
|
||||
|
||||
<!--- ...after we let the api developer know all of the request details first... --->
|
||||
<cfset m.beforeOnTaffyRequest = getTickCount() />
|
||||
<cfset _taffyRequest.continue = onTaffyRequest(
|
||||
_taffyRequest.verb
|
||||
@@ -584,7 +500,6 @@
|
||||
<cfset m.otrTime = m.afterOnTaffyRequest - m.beforeOnTaffyRequest />
|
||||
|
||||
<cfif not structKeyExists(_taffyRequest, "continue")>
|
||||
<!--- developer forgot to return true --->
|
||||
<cfthrow
|
||||
message="Error in your onTaffyRequest method"
|
||||
detail="Your onTaffyRequest method returned no value. Expected: Return TRUE or call noData()/representationOf()."
|
||||
@@ -593,19 +508,14 @@
|
||||
</cfif>
|
||||
|
||||
<cfif isObject(_taffyRequest.continue)>
|
||||
<!--- inspection complete but request has been aborted by developer; return custom response --->
|
||||
<cfset _taffyRequest.result = duplicate(_taffyRequest.continue) />
|
||||
<cfset structDelete(_taffyRequest, "continue")/>
|
||||
<cfset m.resourceTime = 0 />
|
||||
<cfelse>
|
||||
<!--- inspection complete and request allowed by developer --->
|
||||
|
||||
<!--- handle requests for simulated responses --->
|
||||
<cfif structKeyExists(_taffyRequest.requestArguments, application._taffy.settings.simulateKey) and _taffyRequest.requestArguments[application._taffy.settings.simulateKey] eq application._taffy.settings.simulatePassword>
|
||||
<!--- is there a simulated response? --->
|
||||
<cfset sampler = 'sample#_taffyRequest.method#Response' />
|
||||
<cfif structKeyExists(_taffyRequest.matchDetails.metadata, sampler)>
|
||||
<!--- get simulated response --->
|
||||
<cfinvoke
|
||||
component="#application._taffy.factory.getBean(_taffyRequest.matchDetails.beanName)#"
|
||||
method="#sampler#"
|
||||
@@ -613,13 +523,10 @@
|
||||
/>
|
||||
<cfset _taffyRequest.result = rep(_taffyRequest.result) />
|
||||
<cfelse>
|
||||
<!--- no method for simulated response, so return 400 --->
|
||||
<cfset _taffyRequest.result = noData().withStatus(400, "No Sample Response Available") />
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<!--- send request to service --->
|
||||
<cfif structKeyExists(_taffyRequest.matchDetails.methods, _taffyRequest.verb)>
|
||||
<!--- check the cache before we call the resource --->
|
||||
<cfset m.cacheCheckTime = getTickCount() />
|
||||
<cfset local.cacheKey = getCacheKey(
|
||||
_taffyRequest.matchDetails.beanName
|
||||
@@ -637,7 +544,6 @@
|
||||
<cfelse>
|
||||
<cfset structDelete(m, "cacheCheckTime") />
|
||||
</cfif>
|
||||
<!--- returns a representation-object --->
|
||||
<cfset m.beforeResource = getTickCount() />
|
||||
<cfinvoke
|
||||
component="#application._taffy.factory.getBean(_taffyRequest.matchDetails.beanName)#"
|
||||
@@ -654,7 +560,6 @@
|
||||
errorcode="taffy.resources.ResourceReturnsNothing"
|
||||
/>
|
||||
</cfif>
|
||||
<!--- If the type returned is not an instance of baseSerializer, wrap it with a call to rep().
|
||||
This way we can directly return the object instead of a serializer from resource actions. --->
|
||||
<cfif !isInstanceOf(_taffyRequest.result, "taffy.core.baseSerializer")>
|
||||
<cfset _taffyRequest.result = rep(_taffyRequest.result) />
|
||||
@@ -666,11 +571,9 @@
|
||||
</cfif>
|
||||
</cfif>
|
||||
<cfelseif NOT listFind(local.allowVerbs,_taffyRequest.verb)>
|
||||
<!--- if the verb is not implemented, refuse the request --->
|
||||
<cfheader name="ALLOW" value="#local.allowVerbs#" />
|
||||
<cfset throwError(405, "Method Not Allowed") />
|
||||
<cfelse>
|
||||
<!--- create dummy response for cross domain OPTIONS request --->
|
||||
<cfset _taffyRequest.resultHeaders = structNew() />
|
||||
<cfset _taffyRequest.statusArgs = structNew() />
|
||||
<cfset _taffyRequest.statusArgs.statusCode = 200 />
|
||||
@@ -679,17 +582,14 @@
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
<!--- make sure the requested mime type is available --->
|
||||
<cfif not mimeSupported(_taffyRequest.returnMimeExt)>
|
||||
<cfset throwError(400, "Requested format not available (#_taffyRequest.returnMimeExt#)") />
|
||||
</cfif>
|
||||
|
||||
<cfif structKeyExists(_taffyRequest,'result')>
|
||||
<!--- get status code --->
|
||||
<cfset _taffyRequest.statusArgs = structNew() />
|
||||
<cfset _taffyRequest.statusArgs.statusCode = _taffyRequest.result.getStatus() />
|
||||
<cfset _taffyRequest.statusArgs.statusText = _taffyRequest.result.getStatusText() />
|
||||
<!--- get custom headers --->
|
||||
<cfinvoke
|
||||
component="#_taffyRequest.result#"
|
||||
method="getHeaders"
|
||||
@@ -701,13 +601,10 @@
|
||||
<cfcontent reset="true" type="#getReturnMimeAsHeader(_taffyRequest.returnMimeExt)#; charset=utf-8" />
|
||||
<cfheader statuscode="#_taffyRequest.statusArgs.statusCode#" statustext="#_taffyRequest.statusArgs.statusText#" />
|
||||
|
||||
<!--- headers --->
|
||||
<cfset addHeaders(_taffyRequest.resultHeaders) />
|
||||
|
||||
<!--- add ALLOW header for current resource, which describes available verbs --->
|
||||
<cfheader name="ALLOW" value="#local.allowVerbs#" />
|
||||
|
||||
<!--- metrics headers that should always apply --->
|
||||
<cfheader name="X-TIME-IN-PARSE" value="#m.parseTime#" />
|
||||
<cfheader name="X-TIME-IN-ONTAFFYREQUEST" value="#m.otrTime#" />
|
||||
<cfif structKeyExists(m, "resourceTime")>
|
||||
@@ -730,7 +627,6 @@
|
||||
<cfset local.exposeHeaderList = listAppend(local.exposeHeaderList, "Etag") />
|
||||
</cfif>
|
||||
<cfloop list="#local.exposeHeaderList#" index="local.exposeHeader">
|
||||
<!--- filter out default simple response headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers --->
|
||||
<cfif not listFindNoCase("Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma", local.exposeHeader)>
|
||||
<cfset local.exposeHeaderValue = listAppend(local.exposeHeaderValue, local.exposeHeader) />
|
||||
</cfif>
|
||||
@@ -740,13 +636,11 @@
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<!--- result data --->
|
||||
<cfif structKeyExists(_taffyRequest,'result')>
|
||||
<cfset _taffyRequest.resultType = _taffyRequest.result.getType() />
|
||||
<cfset local.resultSerialized = '' />
|
||||
|
||||
<cfif _taffyRequest.resultType eq "textual">
|
||||
<!--- serialize the representation's data into the requested mime type --->
|
||||
<cfset _taffyRequest.metrics.beforeSerialize = getTickCount() />
|
||||
<cfinvoke
|
||||
component="#_taffyRequest.result#"
|
||||
@@ -757,16 +651,12 @@
|
||||
<cfset m.serializeTime = m.afterSerialize - m.beforeSerialize />
|
||||
<cfheader name="X-TIME-IN-SERIALIZE" value="#m.serializeTime#" />
|
||||
|
||||
<!--- apply jsonp wrapper if requested --->
|
||||
<cfif structKeyExists(_taffyRequest, "jsonpCallback")>
|
||||
<cfset _taffyRequest.resultSerialized = _taffyRequest.jsonpCallback & "(" & _taffyRequest.resultSerialized & ");" />
|
||||
</cfif>
|
||||
|
||||
<!--- don't return data if etags are enabled and the data hasn't changed --->
|
||||
<cfif application._taffy.settings.useEtags and _taffyRequest.verb eq "GET">
|
||||
<!--- etag values are quoted per: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag --->
|
||||
<cfif structKeyExists(server, "lucee")>
|
||||
<!--- hashCode() will not work for lucee, see issue #354 --->
|
||||
<cfset _taffyRequest.serverEtag = '"' & hash(_taffyRequest.resultSerialized) & '"' />
|
||||
<cfelse>
|
||||
<cfset _taffyRequest.serverEtag = '"' & _taffyRequest.result.getData().hashCode() & '"' />
|
||||
@@ -797,7 +687,6 @@
|
||||
<cfif _taffyRequest.resultSerialized neq ('"' & '"')>
|
||||
<cfset local.resultSerialized = _taffyRequest.resultSerialized />
|
||||
</cfif>
|
||||
<!--- debug output --->
|
||||
<cfif structKeyExists(url, application._taffy.settings.debugKey)>
|
||||
<cfset local.debug = true />
|
||||
</cfif>
|
||||
@@ -833,7 +722,6 @@
|
||||
<cfset local.result = _taffyRequest.result.getData() />
|
||||
</cfif>
|
||||
|
||||
<!--- ...after the service has finished... --->
|
||||
<cfset m.beforeOnTaffyRequestEnd = getTickCount() />
|
||||
<cfset onTaffyRequestEnd(
|
||||
_taffyRequest.verb
|
||||
@@ -853,7 +741,6 @@
|
||||
<cfif len(trim(local.resultSerialized))>
|
||||
<cfoutput>#local.resultSerialized#</cfoutput>
|
||||
</cfif>
|
||||
<!--- debug output --->
|
||||
<cfif local.debug>
|
||||
<cfoutput><h3>Request Details:</h3><cfdump var="#_taffyRequest#"></cfoutput>
|
||||
</cfif>
|
||||
@@ -862,9 +749,4 @@
|
||||
</cffunction>
|
||||
|
||||
|
||||
<!--- <cffunction name="checkForLocalDebug">
|
||||
<cfreturn fileExists("#GetDirectoryFromPath(GetCurrentTemplatePath())#/etc/local-debug")>
|
||||
</cffunction> --->
|
||||
|
||||
|
||||
</cfcomponent>
|
||||
|
||||
@@ -1,120 +1,57 @@
|
||||
component /*https://www.bennadel.com/blog/2976-trying-to-generate-cryptographically-strong-random-tokens-in-coldfusion.htm*/
|
||||
component
|
||||
output = false
|
||||
hint = "Генерирует случайные токены с помощью Java SecureRandom."
|
||||
{
|
||||
|
||||
/**
|
||||
* Инициализирует генератор токенов.
|
||||
*
|
||||
* @output false
|
||||
*/
|
||||
public any function init() {
|
||||
|
||||
// Реализация генератора, используемая для построения случайных токенов.
|
||||
// SHA1PRNG не является алгоритмом по умолчанию во всех реализациях JVM,
|
||||
// поэтому он задается явно для предсказуемого поведения.
|
||||
generator = createObject( "java", "java.security.SecureRandom" )
|
||||
.getInstance(
|
||||
javaCast( "string", "SHA1PRNG" ),
|
||||
javaCast( "string", "SUN" )
|
||||
)
|
||||
;
|
||||
|
||||
// После инициализации нужно сгенерировать случайный байт,
|
||||
// чтобы генератор сам засеялся через общий источник seed.
|
||||
// Это может блокироваться до накопления достаточной энтропии,
|
||||
// поэтому операция выполняется при инициализации, а не при первом использовании.
|
||||
generator.nextBytes( charsetDecode( " ", "utf-8" ) );
|
||||
|
||||
// Момент следующего пересева генератора.
|
||||
// Это снижает риск слишком долгой работы с одним и тем же seed.
|
||||
reseedAt = getNextReseedAt();
|
||||
|
||||
return( this );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Публичные методы.
|
||||
|
||||
|
||||
/**
|
||||
* Генерирует криптографически стойкий токен из заданного числа случайных байтов.
|
||||
* Байт-массив кодируется в форму, пригодную для использования в URL.
|
||||
*
|
||||
* @byteCount Количество случайных байтов для генерации токена.
|
||||
* @output false
|
||||
*/
|
||||
public string function nextToken( numeric byteCount = 32 ) {
|
||||
|
||||
// Проверяем, нужен ли пересев генератора.
|
||||
if ( now() >= reseedAt ) {
|
||||
|
||||
// Пересев выполняется под lock, чтобы уменьшить гонки между потоками.
|
||||
// Если lock не получен вовремя, поток продолжает работу с текущим состоянием генератора.
|
||||
lock
|
||||
name = "TokenGenerator.reseedCheck"
|
||||
type = "exclusive"
|
||||
timeout = 1
|
||||
throwOnTimeout = false
|
||||
{
|
||||
|
||||
// Повторная проверка внутри lock: другой поток мог уже обновить seed.
|
||||
if ( now() >= reseedAt ) {
|
||||
|
||||
reseedAt = getNextReseedAt();
|
||||
|
||||
// Новый seed добавляется к уже существующему внутреннему состоянию генератора.
|
||||
generator.setSeed( generator.generateSeed( javaCast( "int", 32 ) ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Создаем буфер байтов, в который будут записаны случайные значения.
|
||||
var byteBuffer = charsetDecode( repeatString( " ", byteCount ), "utf-8" );
|
||||
|
||||
generator.nextBytes( byteBuffer );
|
||||
|
||||
return( encodeBytes( byteBuffer ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Приватные методы.
|
||||
|
||||
|
||||
/**
|
||||
* Кодирует массив байтов в строку токена.
|
||||
*
|
||||
* @bytes Кодируемый массив байтов.
|
||||
* @output false
|
||||
*/
|
||||
private string function encodeBytes( required binary bytes ) {
|
||||
|
||||
var token = binaryEncode( bytes, "base64" ); // *** вот поэтому длина отличается от заявленной
|
||||
|
||||
// мы хотим убрать все спецсимволы, потому что мы используем токен в качестве псевдослучайного суффикса
|
||||
var token = binaryEncode( bytes, "base64" );
|
||||
token = replace( token, "+", "a", "all" );
|
||||
token = replace( token, "/", "b", "all" );
|
||||
token = replace( token, "=", "c", "all" );
|
||||
|
||||
return( token );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Вычисляет время следующего пересева генератора.
|
||||
*
|
||||
* @output false
|
||||
*/
|
||||
private date function getNextReseedAt() {
|
||||
|
||||
return( dateAdd( "h", 1, now() ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
<cfset this.helper=CreateObject("component","lib.rest_api_helper")/>
|
||||
</cfsilent>
|
||||
|
||||
<!---спецификация полей, пригодных для фильтрации (?и сортировки)--->
|
||||
<cfset this.fieldsSpec={
|
||||
svc_id={prefix="r", type="integer"},
|
||||
resource_realm_id={prefix="r", type="integer"},
|
||||
@@ -24,11 +23,9 @@
|
||||
<cfset local={}/>
|
||||
|
||||
|
||||
<!---разбор и проверка параметров запроса--->
|
||||
<cftry>
|
||||
<cfset this.helper.validateField(arguments, "svcId", "integer")/>
|
||||
|
||||
<!---мы мирно игнорируем поля, отсутствующие в спецификации, что позволяет не делать исключения для orderBy и т.п.--->
|
||||
|
||||
<cfset var filter=this.helper.parseFilterParams(this.fieldsSpec)/>
|
||||
|
||||
<cfcatch type="invalidParamValue">
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
<cfargument name="bookmarkUid" type="string" required=true hint="type:guid"/>
|
||||
<cfargument name="bookmark" type="string" required=false hint="type:string"/>
|
||||
<cfargument name="descr" type="string" required=false hint="type:string (no cleanup here!)"/>
|
||||
<cfargument name="url" type="string" required=false hint="type:string description: url"/><!--- чистить против XSS --->
|
||||
<cfargument name="iconUrl" type="string" required=false hint="type:string description: url иконки"/><!--- чистить против XSS --->
|
||||
<cfargument name="url" type="string" required=false hint="type:string description: url"/>
|
||||
<cfargument name="iconUrl" type="string" required=false hint="type:string description: url иконки"/>
|
||||
<cfargument name="sort" type="string" required=false hint="type:integer description: целое число для сортировки"/>
|
||||
<cfargument name="isEnabled" type="string" required=false hint="type:boolean description: вкл"/>
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<cfset this.helper=CreateObject("component","lib.rest_api_helper")/>
|
||||
</cfsilent>
|
||||
|
||||
<!---спецификация полей, пригодных для фильтрации (?и сортировки)--->
|
||||
<cfset this.fieldsSpec={
|
||||
bookmark_uid={prefix="b", type="guid"},
|
||||
dt_created={prefix="b", type="date"},
|
||||
@@ -20,8 +19,6 @@
|
||||
}
|
||||
/>
|
||||
|
||||
<!--- предполагается показывать букмарки только "настоящим" клиентам, поэтому используем contragent_id как признак своих--->
|
||||
|
||||
<cffunction name="get" hint="Список букмарков">
|
||||
<cfargument name="pageSize" type="string" hint="type:integer" default="100"/>
|
||||
<cfargument name="page" type="string" hint="type:integer" default="1"/>
|
||||
@@ -31,12 +28,10 @@
|
||||
<cftry>
|
||||
|
||||
|
||||
<!---разбор и проверка параметров запроса--->
|
||||
<cftry>
|
||||
<cfset this.helper.validateField(arguments, "pageSize", "integer")/>
|
||||
<cfset this.helper.validateField(arguments, "page", "integer")/>
|
||||
|
||||
<!---мы мирно игнорируем поля, отсутствующие в спецификации, что позволяет не делать исключения для orderBy и т.п.--->
|
||||
<cfset var filter=this.helper.parseFilterParams(this.fieldsSpec)/>
|
||||
|
||||
<cfcatch type="invalidParamValue">
|
||||
@@ -68,7 +63,7 @@
|
||||
from bookmark b
|
||||
where 1=1 <m:filter_build filter=#filter#/>
|
||||
AND (b.contragent_id = <cfqueryparam cfsqltype="cf_sql_integer" value=#arguments.contragentId# null=#!isNumeric(arguments.contragentId)#/>
|
||||
OR b.contragent_id=-1)/*общая букмарка*/
|
||||
OR b.contragent_id=-1)
|
||||
order by b.contragent_id desc, b.sort asc
|
||||
limit #maxrows#
|
||||
</cfquery>
|
||||
@@ -108,10 +103,10 @@
|
||||
|
||||
|
||||
<cffunction name="post" hint="Создание нового букмарка.">
|
||||
<cfargument name="bookmark" type="string" required=true hint="type:string description: заголовок"/><!--- чистить против XSS --->
|
||||
<cfargument name="bookmark" type="string" required=true hint="type:string description: заголовок"/>
|
||||
<cfargument name="descr" type="string" required=false default="" hint="type:boolean description: пользовательское примечание"/>
|
||||
<cfargument name="url" type="string" required=false default="" hint="type:string description: url"/><!--- чистить против XSS --->
|
||||
<cfargument name="iconUrl" type="string" required=false default="" hint="type:string description: url иконки"/><!--- чистить против XSS --->
|
||||
<cfargument name="url" type="string" required=false default="" hint="type:string description: url"/>
|
||||
<cfargument name="iconUrl" type="string" required=false default="" hint="type:string description: url иконки"/>
|
||||
<cfargument name="sort" type="string" required=false default="100" hint="type:integer description: целое число для сортировки"/>
|
||||
<cfargument name="isEnabled" type="string" required=false default="1" hint="type:boolean description: вкл"/>
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<cfset this.helper=CreateObject("component","lib.rest_api_helper")/>
|
||||
</cfsilent>
|
||||
|
||||
<!--- Спецификация полей, пригодных для фильтрации и сортировки --->
|
||||
<cfset this.fieldsSpec={
|
||||
service_param_id={prefix="p", type="cf_sql_integer"}
|
||||
,service_id={prefix="p", type="cf_sql_integer"}
|
||||
@@ -50,8 +49,6 @@
|
||||
}
|
||||
/>
|
||||
|
||||
<!--- предполагается показывать букмарки только "настоящим" клиентам, поэтому используем contragent_id как признак своих--->
|
||||
|
||||
<cffunction name="get" hint="Каталог конкретных услуг">
|
||||
<cfargument name="pageSize" type="string" hint="type:integer" default="100"/>
|
||||
<cfargument name="page" type="string" hint="type:integer" default="1"/>
|
||||
@@ -61,12 +58,10 @@
|
||||
<cftry>
|
||||
|
||||
|
||||
<!--- Разбор и проверка параметров запроса --->
|
||||
<cftry>
|
||||
<cfset this.helper.validateField(arguments, "pageSize", "integer")/>
|
||||
<cfset this.helper.validateField(arguments, "page", "integer")/>
|
||||
|
||||
<!--- Поля вне спецификации игнорируются, чтобы не добавлять отдельные исключения для orderBy и похожих параметров. --->
|
||||
<cfset var filter=this.helper.parseFilterParams(this.fieldsSpec)/>
|
||||
|
||||
<cfcatch type="invalidParamValue">
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
).withStatus(404)/>
|
||||
</cfif>
|
||||
|
||||
<!--- Проверяем наличие запущенных операций на данном инстансе --->
|
||||
<cfquery name="local.qCheckStarted" result="local.result">
|
||||
select io.dt_submit, io.dt_finish, io.dt_start, io.submit_result, io.status_url
|
||||
from instance_operation io
|
||||
@@ -87,10 +86,10 @@
|
||||
<cfset local.cfsParamChecker = CreateObject("component", "instance_operation_cfs_param_ls")/>
|
||||
|
||||
<cfloop query=#local.qCheckCfsParams#>
|
||||
<cfif (local.qCheckCfsParams.is_required GT 0 AND NOT len(local.qCheckCfsParams.instance_operation_cfs_param_uid) GT 0)><!--- check CFS param existence --->
|
||||
<cfif (local.qCheckCfsParams.is_required GT 0 AND NOT len(local.qCheckCfsParams.instance_operation_cfs_param_uid) GT 0)>
|
||||
<cfreturn representationOf(this.helper.formatMessage("required CFS parameter #local.qCheckCfsParams.svc_operation_cfs_param# (#local.qCheckCfsParams.svc_operation_cfs_param_id#) is missing", "Missing required CFS parameter")).withStatus(422)/>
|
||||
<cfelse><!--- validate CFS param--->
|
||||
<cfif isValid("guid",qCheckCfsParams.instance_operation_cfs_param_uid)><!--- довольно неуклюжий фикс ошибки для нового параметра. Можно было подставить 00000000-0000-0000-0000-000000000000, все равно дальше подставляется --->
|
||||
<cfelse>
|
||||
<cfif isValid("guid",qCheckCfsParams.instance_operation_cfs_param_uid)>
|
||||
<cfset local.cfsParamChecker.checkParam(local.qCheckCfsParams.svc_operation_cfs_param_id, qCheckCfsParams.param_value, arguments.usrId, qCheckCfsParams.instance_operation_cfs_param_uid)/>
|
||||
<cfelse>
|
||||
<cfset local.cfsParamChecker.checkParam(local.qCheckCfsParams.svc_operation_cfs_param_id, qCheckCfsParams.param_value, arguments.usrId)/>
|
||||
@@ -163,12 +162,10 @@
|
||||
join svc_operation_cfs_param socp on (iocp.svc_operation_cfs_param_id=socp.svc_operation_cfs_param_id)
|
||||
join svc_operation_param sop on (socp.svc_operation_id=sop.svc_operation_id AND socp.svc_operation_cfs_param=sop.svc_operation_param)
|
||||
where iocp.instance_operation_uid=<cfqueryparam cfsqltype="cf_sql_other" value="#arguments.instanceOperationUid#"/>
|
||||
/*PostgreSQL specific*/
|
||||
ON CONFLICT (instance_operation_uid,param)
|
||||
DO UPDATE SET param_value = EXCLUDED.param_value;
|
||||
</cfquery>
|
||||
|
||||
<!--- так яснее, но можно было все в один запрос --->
|
||||
<cfquery name="qWriteRfsParamsFromDefaults">
|
||||
insert into instance_operation_param (instance_operation_uid,param,param_value)
|
||||
select
|
||||
@@ -176,8 +173,7 @@
|
||||
,sop.svc_operation_param
|
||||
,sop.default_value
|
||||
from svc_operation_param sop
|
||||
where sop.svc_operation_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#qSvcOperation.svc_operation_id#"/> AND length(sop.default_value)>0 /***null will be better*/
|
||||
/*PostgreSQL specific*/
|
||||
where sop.svc_operation_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#qSvcOperation.svc_operation_id#"/> AND length(sop.default_value)>0
|
||||
ON CONFLICT (instance_operation_uid,param)
|
||||
DO NOTHING;
|
||||
</cfquery>
|
||||
@@ -220,7 +216,6 @@
|
||||
<cfset var submit_url="#qInstanceOperation.url_prefix##qInstanceOperation.version##qInstanceOperation.url_suffix#"/>
|
||||
</cfif>
|
||||
|
||||
<!--- *** тут нужно бы указать, кто запустил операцию --->
|
||||
<cfquery name="qMarkOperationStart">
|
||||
update instance_operation
|
||||
set dt_submit=<cfqueryparam cfsqltype="cf_sql_timestamp" value=#now()#/>
|
||||
@@ -307,7 +302,6 @@
|
||||
,<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.param#"/>
|
||||
,<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.val#"/>
|
||||
)
|
||||
/*PostgreSQL specific*/
|
||||
ON CONFLICT (instance_operation_uid,param)
|
||||
DO UPDATE SET param_value = EXCLUDED.param_value;
|
||||
</cfquery>
|
||||
@@ -429,7 +423,6 @@
|
||||
where io.instance_operation_uid=<cfqueryparam cfsqltype="cf_sql_other" value="#arguments.instanceOperationUid#" null=#!isValid("guid",arguments.instanceOperationUid)#/>
|
||||
</cfquery>
|
||||
|
||||
<!--- проверяем доступ к RFS параметру resourceRealm данной операции --->
|
||||
<cfquery name="local.qCheckResourceRealmAccess">
|
||||
select r.resource_realm_id, r.resource_realm, iop.param, iop.param_value, a.contract_id, a.is_enabled
|
||||
from resource_realm r
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<cfset this.helper=CreateObject("component","lib.rest_api_helper")/>
|
||||
</cfsilent>
|
||||
|
||||
<!---спецификация полей, пригодных для фильтрации (?и сортировки)--->
|
||||
<cfset this.fieldsSpec={
|
||||
dt_created={prefix="n", type="date"},
|
||||
dt_updated={prefix="n", type="date"},
|
||||
@@ -17,9 +16,6 @@
|
||||
external_code={prefix="n", type="string"}
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<cffunction name="get" hint="Список уведомлений">
|
||||
<cfargument name="pageSize" type="string" hint="type:integer" default="100"/>
|
||||
<cfargument name="page" type="string" hint="type:integer" default="1"/>
|
||||
@@ -28,12 +24,10 @@
|
||||
<cftry>
|
||||
<cfset local={}/>
|
||||
|
||||
<!---разбор и проверка параметров запроса--->
|
||||
<cftry>
|
||||
<cfset this.helper.validateField(arguments, "pageSize", "integer")/>
|
||||
<cfset this.helper.validateField(arguments, "page", "integer")/>
|
||||
|
||||
<!---мы мирно игнорируем поля, отсутствующие в спецификации, что позволяет не делать исключения для orderBy и т.п.--->
|
||||
<cfset var filter=this.helper.parseFilterParams(this.fieldsSpec)/>
|
||||
|
||||
<cfcatch type="invalidParamValue">
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<cfset this.helper=CreateObject("component","lib.rest_api_helper")/>
|
||||
</cfsilent>
|
||||
|
||||
<!---спецификация полей, пригодных для фильтрации (?и сортировки)--->
|
||||
<cfset this.fieldsSpec={
|
||||
resource_realm_id={prefix="r", type="integer"},
|
||||
resource_realm_type_id={prefix="r", type="integer"},
|
||||
@@ -24,12 +23,10 @@
|
||||
<cfset local={}/>
|
||||
|
||||
|
||||
<!---разбор и проверка параметров запроса--->
|
||||
<cftry>
|
||||
<cfset this.helper.validateField(arguments, "pageSize", "integer")/>
|
||||
<cfset this.helper.validateField(arguments, "page", "integer")/>
|
||||
|
||||
<!---мы мирно игнорируем поля, отсутствующие в спецификации, что позволяет не делать исключения для orderBy и т.п.--->
|
||||
<cfset var filter=this.helper.parseFilterParams(this.fieldsSpec)/>
|
||||
|
||||
<cfcatch type="invalidParamValue">
|
||||
@@ -69,7 +66,7 @@
|
||||
OR a.contract_id=0)
|
||||
AND a.is_enabled)
|
||||
where 1=1 <m:filter_build filter=#filter#/>
|
||||
order by <m:order_build sortCollection=#this.helper.parseNumericOrder(local.titleMap, arguments.orderBy)# fieldCount=0/><!---no sort length limit--->
|
||||
order by <m:order_build sortCollection=#this.helper.parseNumericOrder(local.titleMap, arguments.orderBy)# fieldCount=0/>
|
||||
limit #maxrows#
|
||||
</cfquery>
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<cfset this.helper=CreateObject("component","lib.rest_api_helper")/>
|
||||
</cfsilent>
|
||||
|
||||
<!---спецификация полей, пригодных для фильтрации (?и сортировки)--->
|
||||
<cfset this.fieldsSpec={
|
||||
resource_realm_type_id={prefix="r", type="integer"},
|
||||
resource_realm_type={prefix="r", type="string"}
|
||||
@@ -20,12 +19,10 @@
|
||||
<cfset local={}/>
|
||||
|
||||
|
||||
<!---разбор и проверка параметров запроса--->
|
||||
<cftry>
|
||||
<cfset this.helper.validateField(arguments, "pageSize", "integer")/>
|
||||
<cfset this.helper.validateField(arguments, "page", "integer")/>
|
||||
|
||||
<!---мы мирно игнорируем поля, отсутствующие в спецификации, что позволяет не делать исключения для orderBy и т.п.--->
|
||||
<cfset var filter=this.helper.parseFilterParams(this.fieldsSpec)/>
|
||||
|
||||
<cfcatch type="invalidParamValue">
|
||||
@@ -50,7 +47,7 @@
|
||||
</m:field_set>
|
||||
from resource_realm_type t
|
||||
where 1=1 <m:filter_build filter=#filter#/>
|
||||
order by <m:order_build sortCollection=#this.helper.parseNumericOrder(local.titleMap, arguments.orderBy)# fieldCount=0/><!---no sort length limit--->
|
||||
order by <m:order_build sortCollection=#this.helper.parseNumericOrder(local.titleMap, arguments.orderBy)# fieldCount=0/>
|
||||
limit #maxrows#
|
||||
</cfquery>
|
||||
|
||||
|
||||
@@ -1,23 +1,4 @@
|
||||
<cfcomponent extends="taffy.core.resource" taffy:uri="/svcOperationCfsSubparams/compute/{svcOperationCfsSubparamId}" hint="вычисляет выражение в поле expression">
|
||||
<!---
|
||||
вычисляет выражение в поле expression
|
||||
для этого нужен контекст - как минимум, сохраненные параметры, но это не работает при создании нового инстанса,
|
||||
поэтому нужно инициализировать контекст и набивать его всей необходимой информацией
|
||||
что особенно важно для зависимых параметров - нам нужно положить в контекст все параметры, от которых мы зависим
|
||||
чтобы знать, какие параметры передавать - конструкцией для параметра предусмотрено поле depends_on_params (надо будет его сделать вычисляемым), а для субпараметра пока не
|
||||
--->
|
||||
|
||||
<!--- Все методы неявно получают
|
||||
arguments.usrId
|
||||
arguments.contragentId
|
||||
arguments.contractId
|
||||
arguments.specificationId
|
||||
|
||||
arguments.requestArguments.usrId=usrCustomerInfo.usrId; //Integer!
|
||||
arguments.requestArguments.contragentId=usrCustomerInfo.contragentId; //Integer
|
||||
arguments.requestArguments.contractId=usrCustomerInfo.contractId; //Integer
|
||||
arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //Integer
|
||||
--->
|
||||
|
||||
<cfsilent>
|
||||
<cfimport prefix="m" taglib="../lib"/>
|
||||
@@ -26,17 +7,13 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
|
||||
|
||||
|
||||
<cffunction name="get" hint="вычисление возможных значений cубпараметра CFS параметра операции, в текущем контексте">
|
||||
<!--- <cfargument name="instanceOperationCfsParamUid" type="string" required=true hint="type:guid"/> а вот ни фига--->
|
||||
<!--- *** Важно: мы должны уметь посчитать параметр, если он не сохранен, то есть мы знаем его класс, а не инстанс --->
|
||||
<!--- Вероятно, нам не очень нужно вычислять набор значений для инстанса параметра, мы всегда знаем класс --->
|
||||
<!--- контест: --->
|
||||
<cfargument name="svcOperationCfsSubparamId" type="string" required=true hint="type:integer"/>
|
||||
<cfargument name="keys" type="string" default={} hint="type:json keys we depend on: of the param uid itself, or operation uid, instance uid, service operation cfs param - if not all entities intstantiated yet"/>
|
||||
<cfargument name="params" type="string" default="{}" hint="type:json any posted parameters we depend on"/>
|
||||
|
||||
<cftry>
|
||||
<cfset this.helper.validateField(arguments, "svcOperationCfsSubparamId", "integer")/>
|
||||
<cfset this.helper.validateField(arguments, "keys", "json")/> <!--- *** может, не лучшая идея передавать ключ в контексте --->
|
||||
<cfset this.helper.validateField(arguments, "svcOperationCfsSubparamId", "integer")/>
|
||||
<cfset this.helper.validateField(arguments, "keys", "json")/>
|
||||
<cfset this.helper.validateField(arguments, "params", "json")/>
|
||||
<cfcatch type="invalidParamValue">
|
||||
<cfreturn representationOf(this.helper.formatBadRequestError(cfcatch)).withStatus(400)/>
|
||||
@@ -44,12 +21,12 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
|
||||
</cftry>
|
||||
|
||||
<cfset local={}/>
|
||||
<cfset "local.expression" = ""/> <!--- нет смысла выносить это в поля класса, оно нужно только локально --->
|
||||
<cfset "local.expression" = ""/>
|
||||
<cfset "local.calculatedValueList" = ""/>
|
||||
<cfset "local.keys" = deserializeJson(arguments.keys)/>
|
||||
<cfset "local.params" = deserializeJson(arguments.params)/>
|
||||
|
||||
<cfset "local.keys.svcOperationCfsSubparamId" = arguments.svcOperationCfsSubparamId/> <!--- *** сомнительное дело гонять аргументы туда-сюда ---><!--- *** по-моему, не используется, поэтому достанем svcOperationCfsParamId прямо тут --->
|
||||
<cfset "local.keys.svcOperationCfsSubparamId" = arguments.svcOperationCfsSubparamId/>
|
||||
|
||||
<cfquery name="local.qCfsSubparam" result="local.result">
|
||||
select
|
||||
@@ -69,15 +46,14 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
|
||||
</cfif>
|
||||
|
||||
<cfset "local.expression"=local.qCfsSubparam.expression/>
|
||||
<cfset "local.keys.svcOperationCfsParamId" = local.qCfsSubparam.svc_operation_cfs_param_id/>
|
||||
<cfset "local.keys.svcOperationCfsParamId" = local.qCfsSubparam.svc_operation_cfs_param_id/>
|
||||
|
||||
<!--- *** можно обратить внимание, что мы инстанциируем не субпараметр, а параметр (цинично пользуясь их функциональной идентичностью... но некрасиво) --->
|
||||
<cfif len(local.expression)>
|
||||
<cfset local.calculatedValueList=createObject("component","lib.expression_parser")
|
||||
.eval(
|
||||
local.expression,
|
||||
{/*context*/
|
||||
component:"resources.instance_operation_cfs_param", /*param, not subparam*/
|
||||
{
|
||||
component:"resources.instance_operation_cfs_param",
|
||||
keys:#local.keys#,
|
||||
params:#local.params#
|
||||
}
|
||||
@@ -86,12 +62,11 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
|
||||
<cfelse>
|
||||
<cfreturn representationOf(this.helper.formatMessage("Expression Not Found")).withStatus(404)/>
|
||||
</cfif>
|
||||
<!--- Тут нам еще придется сформатировать лист в массив. Но обошлось довольно просто --->
|
||||
<cfset var out=structNew("linked")/>
|
||||
<cfset "out.queryDurationMs"=getTickCount() - request.startTickCount/>
|
||||
<cfset "out.values" = listToArray(local.calculatedValueList)/>
|
||||
<cfset "out.runDurationMs"=getTickCount() - request.startTickCount/>
|
||||
<cfreturn representationOf(out) />
|
||||
</cffunction><!--- get --->
|
||||
</cffunction>
|
||||
|
||||
</cfcomponent>
|
||||
|
||||
Reference in New Issue
Block a user