-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from advanced-security/jeongsolee09/CAP-first-…
…draft Cover CAP's Fluent API to construct `cds.ql` queries
- Loading branch information
Showing
45 changed files
with
2,080 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
lockVersion: 1.0.0 | ||
dependencies: {} | ||
compiled: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
library: true | ||
name: advanced-security/javascript-sap-cap-models | ||
version: 0.3.0 | ||
extensionTargets: | ||
codeql/javascript-all: "^0.8.1" | ||
codeql/javascript-queries: "^0.8.1" | ||
dataExtensions: | ||
- "*.model.yml" |
134 changes: 134 additions & 0 deletions
134
javascript/frameworks/cap/lib/advanced_security/javascript/frameworks/cap/CDS.qll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import javascript | ||
import DataFlow | ||
|
||
module CDS { | ||
// TODO: should this base type be more specific? | ||
abstract class ServiceInstance extends DataFlow::Node { } | ||
|
||
/** | ||
* Call to`cds.serve` | ||
*/ | ||
class CdsServeCall extends ServiceInstance { | ||
CdsServeCall() { this = any(CdsFacade cds).getMember("serve").getACall() } | ||
} | ||
|
||
/** | ||
* call to: | ||
* `new cds.ApplicationService` or `new cds.Service` | ||
*/ | ||
class ServiceConstructor extends ServiceInstance { | ||
ServiceConstructor() { this = any(ApplicationService cds).getAnInstantiation() } | ||
} | ||
|
||
/** | ||
* return value of `cds.connect.to` | ||
*/ | ||
class ConnectTo extends ServiceInstance { | ||
ConnectTo() { this = any(CdsFacade cds).getMember("connect").getMember("to").getACall() } | ||
} | ||
|
||
/** Last argument to the service methods `srv.before`, `srv.on`, and `srv.after` */ | ||
private class RequestHandler extends FunctionNode { } | ||
|
||
private class ErrorHandler extends RequestHandler { } | ||
|
||
/** | ||
* Subclassing ApplicationService via `extends`: | ||
* ```js | ||
* class SomeService extends cds.ApplicationService | ||
* ``` | ||
*/ | ||
class UserDefinedApplicationService extends ClassNode { | ||
UserDefinedApplicationService() { | ||
exists(ApplicationService cdsApplicationService | | ||
this.getASuperClassNode() = cdsApplicationService.asSource() | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Subclassing ApplicationService via `cds.service.impl`: | ||
* ```js | ||
* const cds = require('@sap/cds') | ||
* module.exports = cds.service.impl (function() { ... }) | ||
* ``` | ||
*/ | ||
class OldStyleUserDefinedApplicationService extends MethodCallNode { | ||
OldStyleUserDefinedApplicationService() { | ||
exists(CdsFacade cds | this = cds.getMember("service").getMember("impl").getACall()) | ||
} | ||
} | ||
|
||
/** | ||
* Parameter of a `srv.with` method call: | ||
* ```js | ||
* cds.serve('./srv/cat-service') .with ((srv) => { | ||
* srv.on ('READ','Books', (req) => req.reply([...])) | ||
* }) | ||
* ``` | ||
* | ||
* TODO expand this to capture request handlers registered inside the function | ||
*/ | ||
class WithCallParameter extends RequestHandler { | ||
WithCallParameter() { | ||
exists(MethodCallNode withCall, ServiceInstance svc | | ||
withCall.getArgument(0) = this and | ||
withCall.getMethodName() = "with" and | ||
withCall.getReceiver() = svc | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Parameter of request handler of `_.on`: | ||
* ```js | ||
* _.on ('READ','Books', (req) => req.reply([...])) | ||
* ``` | ||
*/ | ||
class OnNodeParam extends ValueNode, ParameterNode { | ||
MethodCallNode on; | ||
|
||
OnNodeParam() { | ||
exists(FunctionNode handler | | ||
on.getMethodName() = "on" and | ||
on.getLastArgument() = handler and | ||
handler.getLastParameter() = this | ||
) | ||
} | ||
|
||
MethodCallNode getOnNode() { result = on } | ||
} | ||
|
||
/** | ||
* Parameter of request handler of `srv.on`: | ||
* ```js | ||
* this.on ('READ','Books', (req) => req.reply([...])) | ||
* ``` | ||
* not sure how else to know which service is registering the handler | ||
*/ | ||
class RequestSource extends OnNodeParam { | ||
RequestSource() { | ||
// TODO : consider - do we need to actually ever know which service the handler is associated to? | ||
exists(UserDefinedApplicationService svc, FunctionNode init | | ||
svc.getAnInstanceMember() = init and | ||
init.getName() = "init" and | ||
this.getOnNode().getEnclosingFunction() = init.getAstNode() | ||
) | ||
or | ||
exists(WithCallParameter pa | this.getOnNode().getEnclosingFunction() = pa.getFunction()) | ||
} | ||
} | ||
|
||
class ApplicationService extends API::Node { | ||
ApplicationService() { exists(CdsFacade c | this = c.getMember("ApplicationService")) } | ||
} | ||
|
||
/** | ||
* ```js | ||
* const cds = require('@sap/cds') | ||
* ``` | ||
*/ | ||
class CdsFacade extends API::Node { | ||
CdsFacade() { this = API::moduleImport("@sap/cds") } | ||
} | ||
} |
Oops, something went wrong.