Commit 807dc150 authored by Arnaud Fontaine's avatar Arnaud Fontaine

Merge remote-tracking branch 'origin/master' into zope4py2

parents f7d47011 593b6cf6
Pipeline #21141 failed with stage
......@@ -643,34 +643,6 @@ div.download-document-format-list-menu ul li.toggle-hidden-format-dialog-selecti
height:20px;
}
/* DMS PDF navigation */
div.pdf-preview-navigation img{
width: 4px;
height: 8px;
margin-right: 4px;
background-repeat: no-repeat;
vertical-align: middle;
}
div.pdf-preview-navigation img.shaded{
opacity: 0.2;
}
div.pdf-preview-navigation img.first{
background-image:url("km_img/2leftarrowv.png");
}
div.pdf-preview-navigation img.previous{
background-image:url("km_img/1leftarrowv.png");
}
div.pdf-preview-navigation img.next{
background-image:url("km_img/1rightarrowv.png");
}
div.pdf-preview-navigation img.last{
background-image:url("km_img/2rightarrowv.png");
width: 5px;
}
/* Editable mode actions */
.actions{
......
......@@ -146,66 +146,6 @@ function initialize_form(){
}
}
// function make_pdf_navigation_asynchronous_form(){
// /*
// Make default PDF navigation in preview in asynchronous way.
// */
//
// function splitUrl(url){
// jQuery.url.setUrl(image_src)
// base_url = jQuery.url.attr("base") + jQuery.url.attr("path");
// query_dict = {"display": jQuery.url.param("display"),
// "format": jQuery.url.param("format"),
// "resolution:int": jQuery.url.param("resolution:int"),
// "frame": parseInt(jQuery.url.param("frame"))};
// query_string = $.param(query_dict);
// console.log(base_url);
// console.log(query_string);
// }
//
// function loadThumbnail(event){
// event.preventDefault();
// navigation_url = this.href;
//
// image = $("div.pdf-preview-content img");
// image_url = image.attr("src");
//
// // read current image URL
// jQuery.url.setUrl(image_url);
// base_url = jQuery.url.attr("base") + jQuery.url.attr("path");
// query_dict = {"display": jQuery.url.param("display"),
// "format": jQuery.url.param("format"),
// "resolution:int": jQuery.url.param("resolution:int")};
//
//
// // get frame index from navigation link
// jQuery.url.setUrl(navigation_url);
// frame = parseInt(jQuery.url.param("selection_index"))
// query_dict["frame"]=frame;
//
// // construct new thumbnail URL
// query_string = $.param(query_dict);
// new_image_url = base_url + "?" +query_string;
// console.log(new_image_url);
//
// image.attr("src", new_image_url);
//
// }
//
// pdf_preview_navigation = $('div.pdf-preview-navigation');
// if(pdf_preview_navigation.length){
//
// // XXX: set hooks
// // $("div.pdf-preview-navigation a img.first").parent("a").click(loadThumbnail);
// // $("div.pdf-preview-navigation a img.previous").parent("a").click(loadThumbnail);
// // $("div.pdf-preview-navigation a img.next").parent("a").click(loadThumbnail);
// // $("div.pdf-preview-navigation a img.last").parent("a").click(loadThumbnail);
//
// }
// }
// $(document).ready(make_pdf_navigation_asynchronous_form);
jQuery.fn.highlight = function (str, className) {
/*
Highlight search word in HTML content.
......
......@@ -469,16 +469,6 @@ div.bottom_actions button#input-save-view span.image {
background-image: url('<tal:block tal:replace="site_url"/>/images/save-preview.png');
}
div.pdf-preview-navigation {
font-size:120%;
text-align:center;
}
div.pdf-preview-navigation img {
float:none;
margin:0;
}
div.error > div > input,
div.error > div > textarea {
border:1px solid red;
......@@ -687,35 +677,4 @@ div#main_content table.listbox tfoot .pageNavigation button:hover {
background: #eee;
}
/* DMS PDF navigation
XXX: probably part of erp5_dms.bt5 */
div.pdf-preview-navigation img{
width: 22px;
height: 22px;
margin-right: 1px;
background-repeat: no-repeat;
vertical-align: middle;
}
div.pdf-preview-navigation img.shaded{
opacity: 0.2;
}
div.pdf-preview-navigation img.first{
background-image:url("images/2leftarrowb.png");
}
div.pdf-preview-navigation img.previous{
background-image:url("images/1leftarrowb.png");
}
div.pdf-preview-navigation img.next{
background-image:url("images/1rightarrowb.png");
}
div.pdf-preview-navigation img.last{
background-image:url("images/2rightarrowb.png");
}
</tal:block>
\ No newline at end of file
......@@ -27,6 +27,7 @@ from __future__ import absolute_import
#
##############################################################################
import copy
import socket
import urllib
import threading
......@@ -195,6 +196,9 @@ class Message(BaseMessage):
exc_type = None
is_executed = MESSAGE_NOT_EXECUTED
traceback = None
user_name = None
user_object = None
user_folder_path = None
document_uid = None
is_registered = False
line = None
......@@ -224,7 +228,14 @@ class Message(BaseMessage):
# was generated.
# Strip last stack entry, since it will always be the same.
self.call_traceback = ''.join(format_list(extract_stack()[:-1]))
self.user_name = getSecurityManager().getUser().getIdOrUserName()
user = getSecurityManager().getUser()
self.user_object = copy.deepcopy(aq_base(user))
# Note: userfolders are not ERP5 objects, so use OFS API.
self.user_folder_path = getattr(
aq_parent(user),
'getPhysicalPath',
lambda: None,
)()
# Store REQUEST Info
self.request_info = {}
if request is not None:
......@@ -298,31 +309,42 @@ class Message(BaseMessage):
pass
return 1
def changeUser(self, user_name, activity_tool):
def changeUser(self, activity_tool):
"""restore the security context for the calling user."""
portal = activity_tool.getPortalObject()
portal_uf = portal.acl_users
uf = portal_uf
user = uf.getUserById(user_name)
# if the user is not found, try to get it from a parent acl_users
# XXX this is still far from perfect, because we need to store all
# information about the user (like original user folder, roles) to
# replay the activity with exactly the same security context as if
# it had been executed without activity.
if user is None:
uf = portal.aq_parent.acl_users
user = uf.getUserById(user_name)
if user is None and user_name == system_user.getUserName():
# The following logic partly comes from unrestricted_apply()
# implementation in ERP5Type.UnrestrictedMethod but we get roles
# from the portal to have more roles.
uf = portal_uf
role_list = uf.valid_roles()
user = PrivilegedUser(user_name, None, role_list, ()).__of__(uf)
user = self.user_object
if user is None and self.user_name is not None: # BBB
user_name = self.user_name
user_folder = portal_user_folder = portal.acl_users
user = user_folder.getUserById(user_name)
# if the user is not found, try to get it from a parent acl_users
# XXX this is still far from perfect, because we need to store all
# information about the user (like original user folder, roles) to
# replay the activity with exactly the same security context as if
# it had been executed without activity.
if user is None:
user_folder = portal.aq_parent.acl_users
user = user_folder.getUserById(user_name)
if user is None and user_name == system_user.getUserName():
# The following logic partly comes from unrestricted_apply()
# implementation in ERP5Type.UnrestrictedMethod but we get roles
# from the portal to have more roles.
user_folder = portal_user_folder
user = PrivilegedUser(
user_name,
None,
user_folder.valid_roles(),
(),
)
else:
user_folder = portal.getPhysicalRoot().unrestrictedTraverse(
self.user_folder_path,
)
user_name = user.getIdOrUserName()
if user is not None:
user = user.__of__(uf)
user = user.__of__(user_folder)
newSecurityManager(None, user)
transaction.get().setUser(user_name, '/'.join(uf.getPhysicalPath()))
transaction.get().setUser(user_name, '/'.join(user_folder.getPhysicalPath()))
else :
LOG("CMFActivity", WARNING,
"Unable to find user %r in the portal" % user_name)
......@@ -347,7 +369,7 @@ class Message(BaseMessage):
try:
# Change user if required (TO BE DONE)
# We will change the user only in order to execute this method
self.changeUser(self.user_name, activity_tool)
self.changeUser(activity_tool)
# XXX: There is no check to see if user is allowed to access
# that method !
method = getattr(obj, self.method_id)
......@@ -420,7 +442,7 @@ Named Parameters: %r
try:
# Change user if required (TO BE DONE)
# We will change the user only in order to execute this method
user = self.changeUser(self.user_name, activity_tool)
user = self.changeUser(activity_tool)
active_obj = obj.activate(activity=activity, **self.activity_kw)
getattr(active_obj, self.method_id)(*self.args, **self.kw)
finally:
......@@ -1664,7 +1686,7 @@ class ActivityTool (BaseTool):
message = m._message
if user_name != message.user_name:
user_name = message.user_name
message.changeUser(user_name, m.object)
message.changeUser(m.object)
m.result = getattr(m.object, method_id)(*m.args, **m.kw)
except Exception:
m.raised()
......
......@@ -30,6 +30,10 @@ import inspect
import warnings
from functools import wraps
from itertools import product
from AccessControl.SecurityManagement import getSecurityManager
from AccessControl.SecurityManagement import setSecurityManager
from AccessControl.SecurityManagement import newSecurityManager
from Acquisition import aq_base, aq_parent
from Products.ERP5Type.tests.utils import LogInterceptor
from Testing import ZopeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
......@@ -40,6 +44,7 @@ from Products.CMFActivity.Activity.SQLBase import INVOKE_ERROR_STATE
from Products.CMFActivity.Activity.Queue import VALIDATION_ERROR_DELAY
from Products.CMFActivity.Activity.SQLDict import SQLDict
from Products.CMFActivity.Errors import ActivityPendingError, ActivityFlushError
from Products.PluggableAuthService.PropertiedUser import PropertiedUser
from erp5.portal_type import Organisation
from AccessControl.SecurityManagement import newSecurityManager
from zLOG import LOG
......@@ -2798,3 +2803,34 @@ return [x.getObject() for x in context.portal_catalog(limit=100)]
self.portal.portal_activities.manageActivitiesAdvanced()
self.portal.portal_activities.manageLoadBalancing()
self.assertEqual(catched_warnings, [])
@for_each_activity
def testSpawnTimeUserGroupAndRoleUsedDuringExecution(self, activity):
obj = self.portal.organisation_module.newContent(portal_type='Organisation')
self.tic()
# This user cannot be created by userfolder API, validating that activity
# execution does not use it.
# Using a PropertiedUser because it is the lowest-level class which has a
# groups notion.
artificial_user = PropertiedUser(
id='this user does not exist',
login='does not matter',
).__of__(self.portal.acl_users)
artificial_user._addGroups(groups=('group 1', 'group 2'))
artificial_user._addRoles(roles=('role 1', 'role 2'))
initial_security_manager = getSecurityManager()
def checkUserGroupAndRole(organisation_self):
user = getSecurityManager().getUser()
self.assertIs(type(aq_base(user)), PropertiedUser)
self.assertEqual(aq_parent(user), aq_parent(artificial_user))
self.assertEqual(user.getId(), artificial_user.getId())
self.assertItemsEqual(user.getGroups(), artificial_user.getGroups())
self.assertItemsEqual(user.getRoles(), artificial_user.getRoles())
Organisation.checkUserGroupAndRole = checkUserGroupAndRole
try:
newSecurityManager(None, artificial_user)
obj.activate(activity=activity).checkUserGroupAndRole()
self.tic()
finally:
setSecurityManager(initial_security_manager)
del Organisation.checkUserGroupAndRole
......@@ -1162,36 +1162,6 @@ div.search .searchPages .selected{
display:none;
}
/* DMS PDF navigation
XXX: probably part of erp5_dms.bt5 */
div.pdf-preview-navigation img{
width: 22px;
height: 22px;
margin-right: 1px;
background-repeat: no-repeat;
vertical-align: middle;
}
div.pdf-preview-navigation img.shaded{
opacity: 0.2;
}
div.pdf-preview-navigation img.first{
background-image:url("images/2leftarrowb.png");
}
div.pdf-preview-navigation img.previous{
background-image:url("images/1leftarrowb.png");
}
div.pdf-preview-navigation img.next{
background-image:url("images/1rightarrowb.png");
}
div.pdf-preview-navigation img.last{
background-image:url("images/2rightarrowb.png");
}
.horizontal_align_form_box > div.input {
float: right;
width: 70%; /* because label width is 30%*/
......
##############################################################################
#
# Copyright (c) 2001,2002 Zope Foundation and Contributors.
# Copyright (c) 2002,2005 Nexedi SARL and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2001,2002 Zope Corporation and Contributors. All Rights Reserved.
......@@ -22,7 +23,6 @@ from marshal import loads as mloads
from .xyap import NoBlanks
from .xyap import xyap
import re
from marshal import dumps as mdumps
#from zLOG import LOG
......
# -*- coding: utf-8 -*-
"""Yet another XML parser
This is meant to be very simple:
......
......@@ -38,7 +38,6 @@ if WITH_LEGACY_WORKFLOW:
from Products.ERP5Type.patches import BTreeFolder2
if WITH_LEGACY_WORKFLOW:
from Products.ERP5Type.patches import WorkflowTool
from Products.ERP5Type.patches import WorkflowTool
from Products.ERP5Type.patches import DynamicType
from Products.ERP5Type.patches import Expression
from Products.ERP5Type.patches import sqltest
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment