cleanup: strip remaining comment noise

This commit is contained in:
“Naeel”
2026-04-30 07:53:58 +04:00
parent 0c7fd14a3a
commit a4c825db60
12 changed files with 62 additions and 275 deletions
+25
View File
@@ -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
View File
@@ -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>
+2 -65
View File
@@ -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() ) );
}
}
+1 -4
View File
@@ -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">
+2 -2
View File
@@ -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: вкл"/>
+4 -9
View File
@@ -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">
+4 -11
View File
@@ -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
-6
View File
@@ -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">
+1 -4
View File
@@ -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>
+1 -4
View File
@@ -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>