Spring Data JPA with Security EvaluationContextExtensionSupport not working - spring-security

I wanted to use Spring Data JPA's Security Extension support to perform a check on user's authority and accordingly fetch some values. I'm trying to do this as indicated here
Below is my code snippet
#RepositoryRestResource(collectionResourceRel = "ProductStatus", path = "ProductStatus")
public interface IProductStatusRepository extends CrudRepository<ProductStatusEntity, String> {
#Query("SELECT p FROM ProductStatusEntity " +
"?#{hasAuthority('ITManager') ? ' ' : ' WHERE ProductStatusCode NOT IN (\'VAL1\',\'VAL2\',\'VAL3\')'}")
List<ProductStatusEntity> findStatusesByAuthority();
}
I did declare the SecurityEvaluationContextExtension class and securityExtension bean by merely copy pasting the code. But still, the above piece of code doesnt work.
I always get a
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ?
I tried several options in playing around with ?#, :#, hasRole, hasAuthority etc. Nothing seem to work.
Any thoughts on this?

Well this one worked after several trial and errors
#Query("select p from ProductStatusEntity p where p.productStatusCode NOT IN ( ?#{hasAuthority('ITManager') ? ' ' : #settings.productStatusExceptions})")
List<ProductStatusEntity> findStatusesByAuthority();
The problem seems to be that SpEL is only being recognized if there is a WHERE clause specified.. Probably this could be improved.. not sure..

Related

Jena read hook not invoked upon duplicate import read

My problem will probably be explained better with code.
Consider the snippet below:
// First read
OntModel m1 = ModelFactory.createOntologyModel();
RDFDataMgr.read(m1,uri0);
m1.loadImports();
// Second read (from the same URI)
OntModel m2 = ModelFactory.createOntologyModel();
RDFDataMgr.read(m2,uri0);
m2.loadImports();
where uri0 points to a valid RDF file describing an ontology model with n imports.
and the following custom ReadHook (which has been set in advance):
#Override
public String beforeRead(Model model, String source, OntDocumentManager odm) {
System.out.println("BEFORE READ CALLED: " + source);
}
Global FileManager and OntDocumentManager are used with the following settings:
processImports = true;
caching = true;
If I run the snippet above, the model will be read from uri0 and beforeRead will be invoked exactly n times (once for each import).
However, in the second read, beforeRead won't be invoked even once.
How, and what should I reset in order for Jena to invoke beforeRead in the second read as well?
What I have tried so far:
At first I thought it was due to caching being on, but turning it off or clearing it between the first and second read didn't do anything.
I have also tried removing all ignoredImport records from m1. Nothing changed.
Finally got to solve this. The problem was in ModelFactory.createOntologyModel(). Ultimately, this gets translated to ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM_RDFS_INF,null).
All ontology models created with the static OntModelSpec.OWL_MEM_RDFS_INF will have their ImportsModelMaker and some of its other objects shared, which results in a shared state. Apparently, this state has blocked the reading hook to be invoked twice for the same imports.
This can be prevented by creating a custom, independent and non-static OntModelSpec instance and using it when creating an OntModel, for example:
new OntModelSpec( ModelFactory.createMemModelMaker(), new OntDocumentManager(), RDFSRuleReasonerFactory.theInstance(), ProfileRegistry.OWL_LANG );

Rascal: TrafoFields Syntax error: concrete syntax fragment

I'm trying to re-create Tijs' CurryOn16 example "TrafoFields" scraping the code from the video, but using the Java18.rsc grammar instead of his Java15.rsc. I've parsed the Example.java successfully in the repl, like he did in the video, yielding a var pt. I then try to do the transformation with trafoFields(pt). The response I get is:
|project://Rascal-Test/src/TrafoFields.rsc|(235,142,<12,9>,<16,11>): Syntax error: concrete syntax fragment
My TrafoFields.rsc looks like this:
module TrafoFields
import lang::java::\syntax::Java18;
/**
* - Make public fields private
* - add getters and setters
*/
start[CompilationUnit] trafoFields(start[CompilationUnit] cu) {
return innermost visit (cu) {
case (ClassBody)`{
' <ClassBodyDeclaration* cs1>
' public <Type t> <ID f>;
' <ClassBodyDeclaration* cs2>
'}`
=> (ClassBody)`{
' <ClassBodyDeclaration* cs1>
' private <Type t> <ID f>;
' public void <ID setter>(<Type t> x) {
' this.<ID f> = x;
' }
' public <Type t> <ID getter>() {
' return this.<ID f>;
' }
' <ClassBodyDeclaration* cs2>
'}`
when
ID setter := [ID]"set<f>",
ID getter := [ID]"get<f>"
}
}
The only deviation from Tijs' code is that I've changed ClassBodyDec* to ClassBodyDeclaration*, as the grammar has this as a non-terminal. Any hint what else could be wrong?
UPDATE
More non-terminal re-writing adapting to Java18 grammar:
Id => ID
Ah yes, that is the Achilles-heal of concrete syntax usability; parse errors.
Note that a generalized parser (such as GLL which Rascal uses), simulates "unlimited lookahead" and so a parse error may be reported a few characters or even a few lines after the actual cause (but never before!). So shortening the example (delta debugging) will help localize the cause.
My way-of-life in this is:
First replace all pattern holes by concrete Java snippets. I know Java, so I should be able to write a correct fragment that would have matched the holes.
If there is still a parse error, now you check the top-non-terminal. Is it the one you needed? also make sure there is no extra whitespace before the start and after the end of the fragment inside the backquotes. Still a parse error? Write a shorter fragment first for a sub-nonterminal first.
Parse error solved? this means one of the pattern holes was not syntactically correct. The type of the hole is leading here, it should be one of the non-terminals used the grammar literally, and of course at the right spot in the fragment. Add the holes back in one-by-one until you hit the error again. Then you know the cause and probably also the fix.

Grails 3 logging non String object as first argument

In BootStrap.groovy in my Grails 3.3.2 app I get the following exception when logging:
groovy.lang.MissingMethodException: No signature of method: ch.qos.logback.classic.Logger.info() is applicable for argument types: (org.apache.http.message.BasicStatusLine) values: [HTTP/1.1 200 OK]
Here is the log statement:
log.info(resp.statusLine)
I know I can work around this by calling toString() on the info method but that is not a good solution because I may have lots of log statements that I may need to fix to workaround previously valid code. Is there a bug opened for this issue?
Grails 3 uses Logback as the logging library, and it has support for variable replacement that makes logging much more efficient.
Often users log statements like
log.debug('found ' + items.size() + ' items: ' + items)
This is expensive because the expression is concatenated into a single String before calling debug(), and if the level of that logger is not DEBUG or TRACE, then nothing will be logged, so if the concatenated String is large (or if this is called often) then that work is wasted. You can wrap the call in an enabled check:
if (log.isDebugEnabled()) {
log.debug('found ' + items.size() + ' items: ' + items)
}
but this clutters your code. With Logback though you're much better off doing this:
log.debug('found {} items: {}', items.size(), items)
Now you're just passing a simple String plus two args to interpolate at the specified positions, but only if the log statement is enabled for the logger's level. If not the call is almost a no-op.
For your logging statement, you should do this instead:
log.info('{}', resp.statusLine)
or
log.info('Status: {}', resp.statusLine)

Spray : How to Unmarshal a response of JsArray or JsObject (ie JsValue) in pipeline

I am creating a service that aggregates data and will need to be able to read any unknown JSON document. I have the pipeline defined as follows:
private def pipeline = (
addHeader("Accept", "application/json")
~> sendReceive
~> unmarshal[JsObject] // Need this to work for JsObject or JsArray //
~> recover
)
This will work with a JsObject but not a JsArray. If I change it to a JsArray then it will not (of course) work with a JsObject. My recover method returns a JsObject.
I would love to be able to define this as a JsValue or enforce a Root format, but for JsValue I get the following compiler error:
could not find implicit value for evidence parameter of type spray.httpx.unmarshalling.FromResponseUnmarshaller[spray.json.JsValue]
And Root Formats also error.
I am not sure how to accomplish what I need, any help would be appreciated.
Use Either, Eric! :) If the response will be either JsObject or JsArray then Either is good solution.
private def pipeline =
addHeader("Accept", "application/json")
~> sendReceive
~> unmarshal[Either[JsObject, JsArray]]
~> recover
However, beware that unmarshal[Either[JsObject, JsArray]] tries to parse response as JsObject first and if it fails, tries to parse it as JsArray. This may lead some performance issues.
After reviewing #Mustafa's answer I created the following to avoid the potential performance hit. In the end, I really only need a JSON AST to pass on.
In the most simple terms, I simply created a function to handle it:
def unmarshalJSON(httpResponse: HttpResponse): JsValue = {
httpResponse.entity.asString.parseJson
}
and altered below:
private def pipeline = {
addHeader("Accept", "application/json")
~> sendReceive
~> unmarshalJSON
~> recover
}
I would of course want to beef this up a bit for production level code, but this could be another alternative and allows me to return a JsValue. #Mustafa I would be interested to hear your thoughts.

Irony AST generation throws nullreference excepttion

I'm getting started with Irony (version Irony_2012_03_15) but I pretty quickly got stuck when trying to generate an AST. Below is a completely strpped language that throws the exception:
[Language("myLang", "0.1", "Bla Bla")]
public class MyLang: Grammar {
public NModel()
: base(false) {
var number = TerminalFactory.CreateCSharpNumber("number");
var binExpr = new NonTerminal("binExpr", typeof(BinaryOperationNode));
var binOp = new NonTerminal("BinOp");
binExpr.Rule = number + binOp + number;
binOp.Rule = ToTerm("+");
RegisterOperators(1, "+");
//MarkTransient(binOp);
this.Root = binExpr;
this.LanguageFlags = Parsing.LanguageFlags.CreateAst; // if I uncomment this line it throws the error
}
}
As soon as I uncomment the last line it throws a NullReferenceException in the grammar explorer or when i want to parse a test. The error is on AstBuilder.cs line 96:
parseNode.AstNode = config.DefaultNodeCreator();
DefaultNodeCreator is a delegate that has not been set.
I've tried setting things with MarkTransient etc but no dice.
Can someone help me afloat here? I'm proably missing something obvious. Looked for AST tutorials all over the webs but I can't seem to find an explanation on how that works.
Thanks in advance,
Gert-Jan
Once you set the LanguageFlags.CreateAst flag on the grammar, you must provide additional information about how to create the AST.
You're supposed to be able to set AstContext.Default*Type for the whole language, but that is currently bugged.
Set TermFlags.NoAstNode. Irony will ignore this node and its children.
Set AstConfig.NodeCreator. This is a delegate that can do the right thing.
Set AstConfig.NodeType to the type of the AstNode. This type should be accessible, implement IAstInit, and have a public, no-parameters constructor. Accessible in this case means either public or internal with the InternalsVisibleTo attribute.
To be honest, I was facing the same problem and did not understand Jay Bazuzi answer, though it looks like valid one(maybe it's outdated).
If there's anyone like me;
I just inherited my Grammar from Irony.Interpreter.InterpretedLanguageGrammar class, and it works. Also, anyone trying to get AST working, make sure your nodes are "public" :- )
On top of Jay's and Erti-Chris's responses, this thread is also useful:
https://irony.codeplex.com/discussions/361018
The creator of Irony points out the relevant configuration code in InterpretedLanguageGrammar.BuildAst.
HTH

Resources