Plone: get vocabulary in a page template - plone

I'm trying this: tal:define="terms python:context.portal_vocabularies.getVocabularyByName('a_vocabulary').items()"
and the result is
Unauthorized: You are not allowed to access 'portal_vocabularies' in this context
Any idea how to get my vocabulary in a page template?
(It's working for authenticated users. The error is only for anonymous.)

Not sure it's the easiest... Added a browser view:
class AVocabulary(BrowserView):
def __call__(self):
terms = self.context.portal_vocabularies.getVocabularyByName(
'a_vocabulary').items()
res = [(t[0], t[1].title) for t in terms]
return res
it's public
<browser:page
name="get_a_vocabulary"
for="*"
permission="zope2.View"
class=".views.AVocabulary"
/>
and it's working:
tal:define="options python:context.restrictedTraverse('get_a_vocabulary')"

Related

How to add new sub resource to a standard Intershop AbstractResourceObject

I want to introduce a new sub resource to standard Intershop ProductResource
without loosing the product resource context.
E.g In my resource's code, I want to know about the product to which a REST client is referring to /product/SOME/my-sub-resource
How can I do this ?
There is a recipe in "Cookbook - REST Framework":
Add a Resource to an Existing REST API
https://support.intershop.com/kb/index.php/Display/28269L
You need to add a new java class extending com.intershop.component.rest.capi.resource.AbstractRestResource
Register the implementation in a component file
<implementation name="YOUR_NAME"
implements="AbstractRestResource"
class="YOUR_FQNAME_TO_IMPL_CLASS"
factory="JavaBeanFactory">
<requires name="name" contract="String" cardinality="1..1" />
<requires name="subResource" contract="RestResource" cardinality="0..n" />
</implementation>
Instantiate the implementation in a component file
<instance with="YOUR_NAME" name="YOUR_INSTANCE_NAME">
<fulfill requirement="name" value="YOUR_SUBRESOUCE_NAME" />
</instance>
Add as subResource to intershop.WebShop.RESTAPI.ProductResource instance
<fulfill requirement="subResource"
of="intershop.WebShop.RESTAPI.ProductResource"
with="YOUR_INSTANCE_NAME"/>
After that your resource is available under /product/SKU/YOUR_SUBRESOURCE_NAME. Make sure your impl class has a public method and that method is annotated with javax.ws.rs.GET and javax.ws.rs.Produces
#GET
#Produces("application/json")
public SomeRO get()
{
ApplicationBO applicationBO = provider.get();
ProductBORepository productBORep = applicationBO.getRepository(ProductBORepositoryExtension.EXTENSION_ID);
ProductBO product = productBORep.getProductBOBySKU(getParent().getName());
// Do the stuff you want with the product
}

SilverStripe 4 : FunctionalTest "get" method returns 404 status although the page is there.

I am trying to test a controller with this Test class,
<?php
use SilverStripe\Dev\FunctionalTest;
class SitePageControllerTest extends FunctionalTest
{
protected static $fixture_file = 'site/tests/fixturesSitePage.yml';
public function testViewSitePage()
{
$obj = $this->objFromFixture('SitePage', 'page1');
$page = $this->get('page-one/');
$this->assertEquals(200, $page->getStatusCode());
}
}
and Fixture.
SitePage:
page1:
Title: Page One
CanViewType: true
But "$this->get('page-one/');" returns a 404 page.
Pages are versioned, and this one isn't published at the point where you ask for it, so the functional test emulates a frontend web request which is served from the live (published) stage by default.
You can use the draft site by appending ?stage=Stage to your request URL, or by using protected static $use_draft_site = true in your functional test (this is deprecated in 4.2).
Note that FunctionalTest doesn't log a user in, so you may also need to log in with some level of permission i.e. $this->logInWithPermission('ADMIN')
Another option is to publish it using something like: $obj->publishRecursive(); before the get()

plone.registry - How do I capture a change in registry when IRecordModifiedEvent is fired?

I'm trying to replicate an example of detecting the change in registry when IRecordModified is supposed to be fired.
https://pypi.python.org/pypi/plone.app.registry#registry-events
I try to adapt this to what I am doing, but a print statement I placed isn't firing.
In my registry.xml
<registry>
<records interface="my.product.utils.db_settings.IDBSettings">
</registry>
In my events.py
from my.product.utils.db_settings import IDBSettings
#adapter(IDBSettings, IRecordModifiedEvent)
def detectDBSettingsChange(settings, event):
print "detectDBSettingsChange"
In the module db_settings.py, which contain the control panel , I have:
from plone.app.registry.browser import controlpanel
class IDBSettings(Interface):
db_string = schema.TextLine(title=u"Database String",
description=u"String for database connection",
default=u"Some value"
)
class DBSettingsEditForm(controlpanel.RegistryEditForm):
schema = IDBSettings
label = u"Database settings"
description = u"String setup"
def updateFields(self):
super(DBSettingsEditForm, self).updateFields()
def updateWidgets(self):
super(DBSettingsEditForm, self).updateWidgets()
class DBSettingsControlPanel(controlpanel.ControlPanelFormWrapper):
form = DBSettingsEditForm
In my configure.zcml in utils:
<include package="plone.app.registry" />
<browser:page
name="database-settings"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".db_settings.DBSettingsControlPanel"
permission="cmf.ManagePortal"
/>
When I go into the control panel, change the value, and then save, detectDBSettingsChange doesn't seem to work as the print statement is ignored. Am I working with the wrong event to capture the change in my registry?
I think you need a subscriber like described in the docs. I'm not sure that the adapter in your events.py is sufficient. Perhaps you can use provideHandler Method like described in plone.registry
You need to add a subscriber and register it like this in your configure.zcml file:
<configure xmlns="http://namespaces.zope.org/zope">
<subscriber
for="plone.registry.interfaces.IRecordModifiedEvent"
handler="your.package.your_subscriber"
/>
</configure>
Check the collective.fingerpointing package for a working example of this.

How is the plone-overview.pt template rendered in the Zope2 application root (in Plone)?

Plone has a nice hack that does away with the boring Zope Quickstart page that ships with Zope2. It changes this:
Into this:
Relevant code is located in Products/CMFPlone/browser/admin.zcml (https://github.com/plone/Products.CMFPlone/blob/master/Products/CMFPlone/browser/admin.zcml#L35):
<browser:page
for="OFS.interfaces.IApplication"
name="plone-overview"
class=".admin.Overview"
permission="zope.Public"
template="templates/plone-overview.pt"
/>
And that explains why http://localhost:8080/plone-overview renders the plone-overview template, but why/how does the application root i.e. http://localhost:8080 render the same template?
That same ZCML file registers a AppTraverser adapter; this adapter adapts the OFS.interfaces.IApplication object to IRequest to intercept traversal.
In the IRequest adapter publishTraverse() method, when the index_html name is traversed over, the adapter returns the same plone-overview view:
def publishTraverse(self, request, name):
if name == 'index_html':
view = queryMultiAdapter((self.context, request),
Interface, 'plone-overview')
if view is not None:
return view
return DefaultPublishTraverse.publishTraverse(self, request, name)
See the AppTraverser class definition.

How to simulate the #PreAutorize tag in a integration test?

I have the following method in Spring MVC and using Spring Security:
#PreAuthorize("#phoneNumber == authentication.name")
#RequestMapping(value = "/{phoneNumber}/start", method = RequestMethod.POST)
public ModelAndView startUpgrading(#PathVariable("phoneNumber") String phoneNumber,
....
}
I manage to simulate authentication something like this:
public Authentication tryToAuthenticate(String accountName, String password) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(accountName, password);
return authenticationManager.authenticate(token);
}
But I dont know how to set up the authorization with #PreAutorize.
How can I set up my test context correctly such that I dont get access denied ?
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:205)
The annotations ( #PreAuthorize, #PostAuthorize, #PreFilter, #PostFilter ) which support expression attributes to allow pre & post-invocation authorization checks are enabled through the global-method-authority namespace element.
You need to add following code in your application-servlet.xml or security xml file.
<security:global-method-security pre-post-annotations="enabled" >
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="permissionEvaluator"/>
</beans:bean>
Check spring-testcontext-framework and this post answering question very similar to yours.
Sounds like you want to declare a mock version of the bean that does the Authentication. You might need a test context.xml to declare it.
Maybe check this old post and the official documentation 16.3 Method Security Expressions for xml configuration.
I think you need to declare on your xml:
Also your method to authenticate token could be a hasPermisions(). Check 16.3.2 Built-In Expressions

Resources