I want to know how I can access the parsed model of my program. I have a validation check written in xtend which accepts a rule A as it parameter. however I want to search the entire parsed tree and make sure that any other reference to this specific instance of A follows certain specifications.
#Check
def checkActionBelongsToAssociatedRole(ActionDsc act){
var pRole = act.parentRole
var rs = new ResourceSetImpl()
//DONT KNOW IF THIS IS RIGHT
var resource = rs.getResource(URI.createURI("./model/generated/Protocol.ecore"), true)
for(r:resource.allContents.toIterable.filter(typeof(RoleDec))){
if(r.name == pRole.name){
//DO SOMETHING
}
}
}
In the generator file that I have I already get the Resource object as a parameter.
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
//Generate code
}
How can I do the same thing for my validator. Thank you in advance!
act.eResource() allows to access the resource that contains the action.
Related
Looking to add the AuthorizeFilterAttribute or AnonymousFilterAttribute to an endpoint in Swashbuckle's implementation of Swagger so I can see which attribute is used on each endpoint in the generated documentation file in a running webapi that ends in /swagger. Is this currenlty possible?
I specifically would like to add a big bold label that says this endpoint is [Anonymous] or that endpoint is using [Authorize] and have them look differently that the summary or remark text.
Also I would like to be able to filter out all the different types of these restriction filter attributes for each endpoint including [NonAction], [Authorize], and [Anonymous] where one of these might be at the top of each controller endpoint. Maybe even eventually add other types of FilterAttributes besides these on each endpoint.
Currently it looks like only the HTTP Methods, the request and response objects can be retrieved in the current implementation so I was not able to find definitive information on this.
Since this is a Swagger implementation do these .NET specific attribute filters not translate to Swashbuckle b/c they only implement what's in the Swagger specification and nothing else?
Finally are their .NET specific extensions to Swashbuckle's implementation that do this?
Thanks!
For the part adding the label to unprotected methods/actions you could use an operation filter like this
public class UnprotectedOperationFilter : IOperationFilter
{
private bool HasAttribute(MethodInfo methodInfo, Type type, bool inherit)
{
// inhertit = true also checks inherited attributes
var actionAttributes = methodInfo.GetCustomAttributes(inherit);
var controllerAttributes = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(inherit);
var actionAndControllerAttributes = actionAttributes.Union(controllerAttributes);
return actionAndControllerAttributes.Any(attr => attr.GetType() == type);
}
public void Apply(Operation operation, OperationFilterContext context)
{
bool hasAuthorizeAttribute = HasAttribute(context.MethodInfo, typeof(AuthorizeAttribute), true);
bool hasAnonymousAttribute = HasAttribute(context.MethodInfo, typeof(AllowAnonymousAttribute), true);
// so far as I understood the action/operation is public/unprotected
// if there is no authorize or an allow anonymous (allow anonymous overrides all authorize)
bool isAuthorized = hasAuthorizeAttribute && !hasAnonymousAttribute;
if (!isAuthorized)
{
operation.Description =
"<p><bold>BIG BOLD LABEL indicating an UPROTECTED PUBLIC method</bold></p>"
+ operation.Description;
}
}
}
and add it with
services.AddSwaggerGen(c => { c.OperationFilter<UnprotectedOperationFilter>();} );
I didn't understand what you mean with filter out different attributes but I hope the code above helps you to check if the attribute is present and do what you desire to do.
In Vapor, specifically in the class for a custom Leaf tag, how can you retrieve values stored in a context?
I'm trying to implement a tag that takes a string and a path, and renders a link unless the path is the current page, so, for example, #navElement("About Us", "/about") will produce a link to the site's about page on every page except the about page itself. On that page, it should display the text without a link on it.
I don't want to have to pass the current path to the tag every time I use it, so I've stored the request's path in the context, roughly like this (checks omitted):
drop.get(":page"){ request in
return try drop.view.make(thePage, ["path": request.uri.path])
}
I can use #(path) in a template and see the path I expect.
My custom tag is derived from Tag, and its run method receives the context as an argument, and I can see the stored value in there in the debugger – but how do I get at it? The get method in the Context class, which seems to do this, is internal, so I can't use it. There is a comment that says subscripts are to be done, and I assume that this will ultimately be the way to extract values from the context, but in the meantime, is there any way to retrieve them?
Just make the current path one of the arguments to your tag.
Droplet route:
drop.get(":page") { request in
return try drop.view.make(thePage, ["currentPath": request.uri.path])
}
In template:
#navElement("About Us", "/about", currentPath)
Tag:
class NavElement: Tag {
let name = "navElement"
public func run(stem: Stem, context: LeafContext, tagTemplate: TagTemplate, arguments: [Argument]) throws -> Node? {
guard
let linkText = arguments[0].value?.string,
let linkPath = arguments[1].value?.string,
let currentPath = arguments[2].value?.string
else { return nil }
if linkPath == currentPath {
return Node("We are at \(currentPath)")
} else {
return Node("Link \(linkText) to \(linkPath)")
}
}
}
Edit:
I have spoken to the developers of Vapor, and they do not intend to open up access to Context's contents publicly. However, since the queue: List<Node>() is public, you can just copy the get() function into your own extension and then you'll be able to do as you wanted.
From my previous question:
How to use token between action chains, properly?
, Now I know that inside my action#1 method, I have to generate a token name and value using TokenHelper programmatically and add them to ActionContext.getContext().getParameters() before chaining to my action#2. If I do, then tokenSessionInterceptor in action#2 will consume this token and does not return invalid.token.
My searchs say if I use ActionContext.getContext().getParameters().put then I'll get following exception:
Cannot find message associated with key parameterMap.locked
So I searched for ActionContext.setParameters usage. I see Struts itself has used it in one of it's interceptors, org.apache.struts2.interceptor.ActionMappingParametersInteceptor.addParametersToContext(ActionContext, Map) as below:
#Override
protected void addParametersToContext(ActionContext ac, Map newParams) {
Map previousParams = ac.getParameters();
Map combinedParams;
if (previousParams != null) {
combinedParams = new TreeMap(previousParams);
} else {
combinedParams = new TreeMap();
}
combinedParams.putAll(newParams);
ac.setParameters(combinedParams);
}
Is it safe to do same in my own action method rather than an interceptor?! If no, what are alternatives?! Is it possible at all?! I really need to do this in my action chains because it's so hard to rewrite these actions to use redirectAction instead of chain.
I need to log any action made by users in sfDoctrineGuard plugin. Basically I'll need to log:
module/action
date
IP from where users are accessing the application
Any plugin? Is that possible? How?
This could be probably the plugin you need, sfDoctrineGuardLoginHistoryPlugin and allows to extend the information that you save.
Check for more plugins here.
Take a look at the code of the plugin, you just need to change the following file: PluginUserLoginHistoryTable.class.php
Add in the function writeLoginHistory and createHistoryEntry the information you want:
writeLoginHistory(sfEvent $event) {
//... same code than in the plugin
//lets save module and action
if (!isset($request) )
{
$sActionName = sfContext::getInstance()->getActionName();
$sModuleName = sfContext::getInstance()->getModuleName();
}
else
{
if (isset($request["module"]))
{
$sActionName = $request["action"];
$sModuleName = $request["module"];
}
}
//get values from the http bar URL
if (!isset($sModuleName))
{
$sFullURL = sfContext::getInstance()->getRouting()->getCurrentInternalUri();
///... strip action and module name from the above URL
}
}
Remember to pass those values to createHistoryEntry function and also to update that function with more input values to be saved.
How can I pass session variable in symfony model without using sfContext::getInstance()?
The recommended way is called dependency injection, and works like this: you create a setUser() method in your model file, that saves the given parameter to a private property:
class Foo {
private $_user;
public function setUser(myUser $user) {
$this->_user = $user;
}
// ... later:
public function save(Doctrine_Connection $conn = null) {
// use $this->_user to whatever you need
}
}
This looks clumsy, because it is. But without you answering the question what are you trying to do? I cannot give an alternative.
Recommended articles:
What is Dependency Injection? - a post series on Fabien Potencier's blog
Dependency Injection - the design patter in detail on wikipedia
Session variables should be stored as user's attributes.
// in an action:
$this->getUser()->setAttribute('current_order_id', $order_id);
See how to get it back.
// later on, in another action, you can get it as:
$order_id = $this->getUser()->getAttribute('current_order_id', false);
if($order_id!==false)
{
// save to DB
} else {
$this->getUser()->setFlash('error', 'Please selected an order before you can do stuff.');
// redirect and warn the user to selected an order
$this->redirect('orders');
}