From 5f7ee128a856449505308342fa5f59993eb772b6 Mon Sep 17 00:00:00 2001
From: Ivan Tyagov <ivan@nexedi.com>
Date: Tue, 20 May 2008 08:56:08 +0000
Subject: [PATCH] Make it possible to show a login form to user in case user
 can't find a document by its reference in URL traversal. Introduce a new
 property of Web Section for that purpose.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@21026 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/Document/Document.py        | 11 ++++++
 product/ERP5/PropertySheet/WebSection.py |  5 +++
 product/ERP5/tests/testERP5Web.py        | 49 ++++++++++++++++++++++++
 3 files changed, 65 insertions(+)

diff --git a/product/ERP5/Document/Document.py b/product/ERP5/Document/Document.py
index f199ffd6b0..f3bada0cc3 100644
--- a/product/ERP5/Document/Document.py
+++ b/product/ERP5/Document/Document.py
@@ -308,6 +308,17 @@ class PermanentURLMixIn(ExtensibleTraversableMixIn):
                                             original_id=document.getId(),
                                             editable_absolute_url=document.absolute_url()))
       return document.__of__(self)
+    # no document found for current user, still such document may exists
+    # in some cases user (like Anonymous) can not view document according to portal catalog
+    # but we may ask him to login if such a document exists
+    # XXX: make sure document exists
+    if getattr(self,  'isAuthorizationForced',  None) is not None:
+      if self.isAuthorizationForced():
+        # force user to login as specified in Web Section
+        raise Unauthorized
+    else:
+      # force user to login unconditionally of context
+      raise Unauthorized
 
   security.declareProtected(Permissions.View, 'getDocumentValue')
   def getDocumentValue(self, name=None, portal=None, **kw):
diff --git a/product/ERP5/PropertySheet/WebSection.py b/product/ERP5/PropertySheet/WebSection.py
index 255c309021..c7ddfe26bc 100644
--- a/product/ERP5/PropertySheet/WebSection.py
+++ b/product/ERP5/PropertySheet/WebSection.py
@@ -74,6 +74,11 @@ class WebSection:
             'acquisition_accessor_id'       : 'getLayoutConfigurationFormId',
             'acquisition_depends'           : None,
             'mode'        : '' },
+          {   'id'          : 'authorization_forced',
+            'description' : 'Force authorization for anonymous user if document can not be found.',
+            'type'        : 'boolean',
+            'default':  0, 
+            'mode'        : 'rw' },
     )
 
     _categories = ('aggregate', )
diff --git a/product/ERP5/tests/testERP5Web.py b/product/ERP5/tests/testERP5Web.py
index 5dd26658ad..ce13bd0eae 100644
--- a/product/ERP5/tests/testERP5Web.py
+++ b/product/ERP5/tests/testERP5Web.py
@@ -30,6 +30,7 @@
 import os
 import unittest
 
+from AccessControl import Unauthorized
 from AccessControl.SecurityManagement import newSecurityManager
 from Testing import ZopeTestCase
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
@@ -314,6 +315,54 @@ class TestERP5Web(ERP5TypeTestCase, ZopeTestCase.Functional):
     self.assertEquals('0.2', default_document.getVersion())
     self.assertEquals('published', default_document.getValidationState())
 
+  def test_06_WebSectionAuthorizationForced(self, quiet=quiet, run=run_all_test):
+    """ Check that when a document is requested within a Web Section we have a chance to 
+        require user to login.
+        Whether or not an user will login is controlled by a property on Web Section (authorization_forced).
+    """
+    if not run:
+      return
+    if not quiet:
+      message = '\ntest_06_WebSectionAuthorizationForced'
+      ZopeTestCase._print(message)
+    request = self.app.REQUEST    
+    website = self.setupWebSite()
+    websection = self.setupWebSection()
+    webpage_list  = self.setupWebSitePages(prefix = 'test-web-page')
+    webpage = webpage_list[0]
+    document_reference = 'default-document-reference'
+    document = self.portal.web_page_module.newContent(
+                                      portal_type = 'Web Page', 
+                                      reference = document_reference)
+    website.setAuthorizationForced(0)  
+    websection.setAuthorizationForced(0)                                      
+    get_transaction().commit()
+    self.tic()
+    
+    # make sure that _getExtensibleContent will return the same document
+    # there's not other way to test otherwise URL traversal
+    self.assertEqual(document.getUid(), 
+                           websection._getExtensibleContent(request,  document_reference).getUid())
+                          
+    # Anonymous User should have in the request header for not found when 
+    # viewing non available document in Web Section (with no authorization_forced)
+    self.logout()
+    self.assertEqual(None,  websection._getExtensibleContent(request,  document_reference))
+    self.assertEqual('404 Not Found',  request.RESPONSE.getHeader('status'))
+    
+    # Anonymous user should be prompted to login when viewing non available document
+    # contained in a Web Page (like ..web_page_module/1/<document_reference>)
+    self.assertRaises(Unauthorized,  webpage._getExtensibleContent,  request,  document_reference)
+       
+    # set authorization_forced flag
+    self.login()
+    websection.setAuthorizationForced(1)
+    
+    # check Unauthorized exception is raised for anonymous
+    # this exception is usually caught and user is redirecetd to login form
+    self.logout()
+    self.assertRaises(Unauthorized,  websection._getExtensibleContent,  request,  document_reference)
+    
 def test_suite():
   suite = unittest.TestSuite()
   suite.addTest(unittest.makeSuite(TestERP5Web))
-- 
2.30.9