Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Romain Courteaud
erp5
Commits
bc17aafd
Commit
bc17aafd
authored
Apr 09, 2024
by
Titouan Soulard
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
erp5_api_style: rewrite most of `jIOWebSection`
parent
0887cfcf
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
92 additions
and
110 deletions
+92
-110
bt5/erp5_api_style/DocumentTemplateItem/portal_components/document.erp5.jIOWebSection.py
...lateItem/portal_components/document.erp5.jIOWebSection.py
+85
-108
bt5/erp5_api_style/SkinTemplateItem/portal_skins/erp5_api_style/ERP5Site_logApiErrorAndReturn.py
...tal_skins/erp5_api_style/ERP5Site_logApiErrorAndReturn.py
+7
-2
No files found.
bt5/erp5_api_style/DocumentTemplateItem/portal_components/document.erp5.jIOWebSection.py
View file @
bc17aafd
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2016 Nexedi SA and Contributors. All Rights Reserved.
# Cédric Le Ninivin <cedric.leninivin@nexedi.com>
# Copyright (c) 2024 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
...
...
@@ -28,140 +27,118 @@
##############################################################################
from
AccessControl
import
ClassSecurityInfo
from
AccessControl
import
Unauthorized
from
Acquisition
import
aq_inner
from
OFS.Traversable
import
NotFound
from
erp5.component.document.WebSection
import
WebSection
from
zExceptions
import
NotFound
,
Unauthorized
from
Products.ERP5Type
import
Permissions
from
zExceptions
import
HTTPClientError
from
zLOG
import
LOG
,
INFO
from
erp5.component.mixin.DocumentExtensibleTraversableMixin
import
DocumentExtensibleTraversableMixin
from
erp5.component.document.WebSection
import
WebSection
MARKER
=
[]
ALLOWED_MODES
=
[
"put"
,
"get"
,
"post"
,
"allDocs"
]
# Redefine an Unauthorized error to avoid Zope redirecting the user to the main ERP5 login form
class
jIOUnauthorized
(
HTTPClientError
):
errmsg
=
'Unauthorized'
status
=
401
class
jIOAPITraverseErrorWrapper
(
object
):
"""
JSON error object, to avoid ERP5 default error pages.
Publishable but non-Persistent and without Acquisition.
"""
def
__init__
(
self
,
underlyingError
):
HTTPClientError
.
__init__
(
self
)
self
.
underlyingError
=
underlyingError
def
__init__
(
self
,
error_context
,
portal
):
self
.
error_context
=
error_context
self
.
portal
=
portal
# Used for debugging, especially in tests
def
__str__
(
self
):
return
str
(
self
.
underlyingError
)
return
str
(
self
.
error_context
)
def
__call__
(
self
):
portal
=
self
.
portal
# Skin used to allow replacement and because Manager proxy role is needed
portal
.
ERP5Site_logApiErrorAndReturn
(
**
self
.
error_context
)
def
__bytes__
(
self
):
return
bytes
(
self
.
underlyingError
)
def
convertTojIOAPICall
(
function
):
class
jIOMethod
(
object
):
"""
Wrap the method to create a log entry for each invocation to the zope logger
Represents one of the four possible jIO methods.
Publishable but non-Persistent and without Acquisition.
XXX: Acquisition might be suitable here
"""
def
wrapper
(
self
,
*
args
,
**
kwd
):
"""
Log the call, and the result of the call
"""
assert
(
self
.
REQUEST
.
REQUEST_METHOD
==
"POST"
)
def
__init__
(
self
,
mode_name
,
web_section
):
super
(
jIOMethod
,
self
).
__init__
()
self
.
mode_name
=
mode_name
self
.
web_section
=
web_section
def
__call__
(
self
):
self
.
web_section
.
REQUEST
.
response
.
setHeader
(
"Content-Type"
,
"application/json"
)
try
:
self
.
REQUEST
.
response
.
setHeader
(
"Content-Type"
,
"application/json"
)
retval
=
function
(
self
,
*
args
,
**
kwd
)
except
Unauthorized
,
e
:
body
=
self
.
ERP5Site_logApiErrorAndReturn
(
error_code
=
"401"
,
error_message
=
str
(
e
),
error_name
=
"Unauthorized"
)
self
.
REQUEST
.
response
.
setBody
(
body
,
lock
=
True
)
raise
jIOUnauthorized
(
e
)
except
NotFound
,
e
:
LOG
(
'jIOWebSection'
,
INFO
,
'Converting NotFound to NotFound error mesage in JSON,'
,
error
=
True
)
body
=
self
.
ERP5Site_logApiErrorAndReturn
(
error_code
=
"404"
,
error_message
=
str
(
e
),
error_name
=
"NotFound"
)
self
.
REQUEST
.
response
.
setBody
(
body
,
lock
=
True
)
raise
except
:
LOG
(
'jIOWebSection'
,
INFO
,
'Converting Error to InternalError message in JSON,'
,
error
=
True
)
body
=
self
.
ERP5Site_logApiErrorAndReturn
(
error_code
=
"500"
,
error_message
=
"Internal Server Error"
,
error_name
=
"InternalError"
return
self
.
web_section
.
ERP5Site_asjIOStyle
(
mode
=
self
.
mode_name
,
text_content
=
self
.
web_section
.
REQUEST
.
get
(
"BODY"
),
data_dict
=
None
,
)
self
.
REQUEST
.
response
.
setBody
(
body
,
lock
=
True
)
raise
return
'%s'
%
retval
wrapper
.
__doc__
=
function
.
__doc__
return
wrapper
except
Exception
as
e
:
error_context
=
{
"error_code"
:
500
,
"error_name"
:
"API-INTERNAL-ERROR"
,
"error_message"
:
str
(
e
)
}
# This NotFound catches instance of objects not found inside API call
if
isinstance
(
e
,
NotFound
):
error_context
[
"error_code"
]
=
404
error_context
[
"error_name"
]
=
"API-NOT-FOUND"
elif
isinstance
(
e
,
Unauthorized
):
error_context
[
"error_code"
]
=
403
error_context
[
"error_name"
]
=
"API-UNAUTHORIZED"
# Avoid information leak when Unauthorized
del
error_context
[
"error_message"
]
# Skin used to allow replacement and because Manager proxy role is needed
self
.
web_section
.
ERP5Site_logApiErrorAndReturn
(
**
error_context
)
class
jIOWebSection
(
WebSection
):
"""
This Web Section is a wrapper to jIO to pass content in the body
"""
portal_type
=
"jIO Web Section"
portal_type
=
'jIO Web Section'
# Declarative security
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getLayoutProperty'
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
"getLayoutProperty"
)
def
getLayoutProperty
(
self
,
key
,
default
=
None
):
"""
A simple method to get a property of the current by
acquiring it from the current section or its parents.
A simple method to get a property of the current by
acquiring it from the current section or its parents.
"""
section
=
aq_inner
(
self
)
while
section
.
getPortalType
()
in
(
'Web Section'
,
'Web Site'
,
'Static Web Section'
,
'Static Web Site'
,
'jIO Web Section'
):
while
section
.
getPortalType
()
in
(
"Web Section"
,
"Web Site"
,
"Static Web Section"
,
"Static Web Site"
,
"jIO Web Section"
):
result
=
section
.
getProperty
(
key
,
MARKER
)
if
result
not
in
(
MARKER
,
None
):
return
result
section
=
section
.
aq_parent
return
default
@
convertTojIOAPICall
def
_asjIOStyle
(
self
,
mode
,
text_content
=
""
,
data_dict
=
None
):
return
self
.
ERP5Site_asjIOStyle
(
mode
=
mode
,
text_content
=
text_content
,
data_dict
=
data_dict
,
)
security
.
declareProtected
(
Permissions
.
View
,
'get'
)
def
get
(
self
):
#pylint:disable=arguments-differ
"""
Taken from WebSection Bobo Traverse, the difference is that
__bobo_traverse__ from DocumentExtensibleTraversableMixin is not called
"""
# Register current web site physical path for later URL generation
return
self
.
_asjIOStyle
(
mode
=
"get"
,
text_content
=
self
.
REQUEST
.
get
(
'BODY'
))
security
.
declareProtected
(
Permissions
.
View
,
"_bobo_traverse__"
)
def
__bobo_traverse__
(
self
,
request
,
name
):
if
name
in
ALLOWED_MODES
:
return
jIOMethod
(
name
,
self
)
security
.
declareProtected
(
Permissions
.
View
,
'post'
)
def
post
(
self
):
"""
Taken from WebSection Bobo Traverse, the difference is that
__bobo_traverse__ from DocumentExtensibleTraversableMixin is not called
"""
# Register current web site physical path for later URL generation
return
self
.
_asjIOStyle
(
mode
=
"post"
,
text_content
=
self
.
REQUEST
.
get
(
'BODY'
))
security
.
declareProtected
(
Permissions
.
View
,
'put'
)
def
put
(
self
):
"""
Taken from WebSection Bobo Traverse, the difference is that
__bobo_traverse__ from DocumentExtensibleTraversableMixin is not called
"""
# Register current web site physical path for later URL generation
return
self
.
_asjIOStyle
(
mode
=
"put"
,
text_content
=
self
.
REQUEST
.
get
(
'BODY'
))
security
.
declareProtected
(
Permissions
.
View
,
'allDocs'
)
def
allDocs
(
self
):
"""
Taken from WebSection Bobo Traverse, the difference is that
__bobo_traverse__ from DocumentExtensibleTraversableMixin is not called
"""
# Register current web site physical path for later URL generation
return
self
.
_asjIOStyle
(
mode
=
"allDocs"
,
text_content
=
self
.
REQUEST
.
get
(
'BODY'
))
document
=
None
try
:
# Inheritance as follows: jIOWebSection <| WebSection <| (Domain, DocumentExtensibleTraversableMixin)
# Use DocumentExtensibleTraversableMixin traversal to avoid ERP5 HTML 404 page.
document
=
DocumentExtensibleTraversableMixin
.
__bobo_traverse__
(
self
,
request
,
name
)
# This NotFound catches objects not found during traversal
except
NotFound
as
e
:
error_context
=
{
"error_code"
:
404
,
"error_message"
:
str
(
e
),
"error_name"
:
"NotFound"
,
"text_content"
:
request
.
get
(
"BODY"
)
}
document
=
jIOAPITraverseErrorWrapper
(
error_context
,
self
.
getPortalObject
())
return
document
bt5/erp5_api_style/SkinTemplateItem/portal_skins/erp5_api_style/ERP5Site_logApiErrorAndReturn.py
View file @
bc17aafd
...
...
@@ -7,7 +7,6 @@ error = context.getPortalObject().error_record_module.newContent(
description
=
str
(
error_message
),
text_content
=
str
(
text_content
)
)
container
.
REQUEST
.
RESPONSE
.
setStatus
(
error_code
,
lock
=
True
)
# We follow here Paypal api guideline
# https://github.com/paypal/api-standards/blob/master/api-style-guide.md#error-schema
error_dict
=
{
...
...
@@ -24,4 +23,10 @@ if error_link:
if
detail_list
:
error_dict
[
"details"
]
=
detail_list
error
.
setDescription
(
str
(
error_message
)
+
"
\
n
"
.
join
([
str
(
x
)
for
x
in
detail_list
]))
return
json
.
dumps
(
error_dict
,
indent
=
2
)
serialized_error
=
json
.
dumps
(
error_dict
,
indent
=
2
)
context
.
REQUEST
.
response
.
setHeader
(
"Content-Type"
,
"application/json"
)
context
.
REQUEST
.
response
.
setStatus
(
error_code
,
lock
=
True
)
context
.
REQUEST
.
response
.
setBody
(
serialized_error
,
lock
=
True
)
return
serialized_error
Romain Courteaud
@romain
mentioned in commit
7fbde6a9
·
Nov 20, 2024
mentioned in commit
7fbde6a9
mentioned in commit 7fbde6a950d94b1c61b22c86dac6e35f716f88ed
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment