182 lines
5.6 KiB
Python
182 lines
5.6 KiB
Python
from typing import Union, List, Optional
|
|
|
|
import requests
|
|
from urllib.parse import urljoin
|
|
|
|
from .simplenode import SimpleNode
|
|
from .patchbuilder import PatchBuilder
|
|
|
|
# TODO validation
|
|
|
|
"""
|
|
http://localhost:4502/crx/de/init.jsp?_dc=1549392939742
|
|
http://localhost:4502/crx/de/nodetypes.jsp?_dc=1549392939958
|
|
http://localhost:4502/crx/server/crx.default/jcr%3aroot/libs.1.json?_dc=1549392123434&node=xnode-265
|
|
http://localhost:4502/crx/de/query.jsp?_dc=1549392245191&_charset_=utf-8&type=xpath&stmt=%2Fjcr%3Aroot%2Fbin%2F%2F*%5Bjcr%3Acontains(.%2C%20%27asdf%27)%5D%20order%20by%20%40jcr%3Ascore&showResults=true
|
|
http://app30-prd-asd.sbnl.vancis.nl:4502/bin/wcm/references.json?path=%2Fcontent%2Fdam%2Fbeeldbank%2F_0005_home_algemeen.png&predicate=wcmcontent&_charset_=utf-8
|
|
|
|
Download:
|
|
http://app30-prd-asd.sbnl.vancis.nl:4502/crx/server/crx.default/jcr:root/content/dam/beeldbank/vrouw-direct-naar.jpg/jcr:content/renditions/original/jcr:content/jcr:data
|
|
OR
|
|
download.jsp?path=%2Fcontent%2Fdam%2Fbeeldbank%2Fvrouw-direct-naar.jpg%2Fjcr%3Acontent%2Frenditions%2Foriginal%2Fjcr%3Acontent%2Fjcr%3Adata&index=0
|
|
"""
|
|
|
|
CRX_SERVER_ROOT = '/crx/server/crx.default/jcr:root/'
|
|
CRX_QUERY = '/crx/de/query.jsp'
|
|
WCM_REFERENCES = '/bin/wcm/references.json'
|
|
|
|
JSON_DATA_EXTENSION = '.1.json'
|
|
|
|
QUERY_TYPES = {
|
|
'XPATH': 'xpath',
|
|
'SQL': 'sql',
|
|
'SQL2': 'JCR-SQL2'
|
|
}
|
|
|
|
|
|
class CrxException(ValueError):
|
|
pass
|
|
|
|
|
|
class Connection:
|
|
def __init__(self,
|
|
host: str = 'localhost',
|
|
port: int = 4502,
|
|
protocol: str = 'http',
|
|
root: str = CRX_SERVER_ROOT,
|
|
query: str = CRX_QUERY,
|
|
image_references: str = WCM_REFERENCES):
|
|
|
|
self._host = f'{protocol}://{host}:{port}'
|
|
self._data_root = self._host + root
|
|
self._query_path = self._host + query
|
|
self._image_references = self._host + image_references
|
|
|
|
self._session = requests.session()
|
|
|
|
self._patch_builder: Optional[PatchBuilder] = None
|
|
|
|
def login_basic(self, username: str, password: str):
|
|
"""
|
|
Set the credentials to use for this connection.
|
|
|
|
Args:
|
|
username: The username to use
|
|
password: The password to use
|
|
"""
|
|
self._session.auth = (username, password)
|
|
|
|
def query(self, query: str, query_type: str = 'SQL2') -> List[str]:
|
|
"""
|
|
Perform an query and return the matching paths.
|
|
Query may be an XPATH, SQL or SQL2 Query
|
|
|
|
Args:
|
|
query: The query to perform
|
|
query_type: The type of the query (defaults to SQL2)
|
|
|
|
Returns:
|
|
The matching paths of the query
|
|
"""
|
|
response = self._session.get(self._query_path, params={
|
|
'_charset': 'utf-8',
|
|
'type': QUERY_TYPES.get(query_type, query_type),
|
|
'stmt': query,
|
|
'showResults': 'true'
|
|
})
|
|
data = response.json()
|
|
|
|
# TODO check for error
|
|
|
|
return list(map(lambda node: node['path'], data['results']))
|
|
|
|
def get_image_references(self, path: str):
|
|
"""
|
|
Find all image references for a given image resource.
|
|
This uses the DAM Asset Manager > Image > File References tap's backend
|
|
|
|
Args:
|
|
path: The path of the image to check (no the rendition)
|
|
|
|
Returns:
|
|
The references of the image (see Chrome/Firefox developer tab for details)
|
|
"""
|
|
response = self._session.get(self._image_references, params={
|
|
'path': path
|
|
})
|
|
return response.json()['pages']
|
|
|
|
def get_node_raw(self, path: str):
|
|
"""
|
|
Get the raw JSON dictionary of a node.
|
|
This is mostly an internal method.
|
|
|
|
Args:
|
|
path: The path of the node
|
|
|
|
Returns:
|
|
A dict representing the node
|
|
"""
|
|
url = urljoin(self._data_root, '.' + path + JSON_DATA_EXTENSION)
|
|
try:
|
|
response = self._session.get(url)
|
|
except requests.exceptions.RequestException as exception:
|
|
raise CrxException() # todo more specific exceptions
|
|
|
|
try:
|
|
data = response.json()
|
|
except ValueError:
|
|
raise # todo
|
|
|
|
return data
|
|
|
|
def get_simple_node(self, path: str) -> SimpleNode:
|
|
"""
|
|
Get a Node as a `SimpleNode` object.
|
|
|
|
Args:
|
|
path: The path of the node
|
|
|
|
Returns:
|
|
The SimpleNode object for that path
|
|
"""
|
|
return SimpleNode(path, self.get_node_raw(path), self)
|
|
|
|
def download_binary(self, path: str) -> bytes:
|
|
"""
|
|
Download the binary data of a node. (usually jcr:data).
|
|
Usually called via `SimpleNode.download()`
|
|
|
|
Args:
|
|
path: The path of the node property to download
|
|
|
|
Returns:
|
|
The binary content of the response
|
|
"""
|
|
# TODO verify if it is not b64 encoded. for some reason it is in FireFox
|
|
resp = self._session.get(
|
|
urljoin(self._data_root, '.' + path)
|
|
)
|
|
return resp.content
|
|
|
|
def rename_node(self, old_path: str, new_path: str):
|
|
diff = f'>{old_path} : {new_path}'
|
|
resp = self._session.post(self._data_root, data={':diff': diff})
|
|
resp.raise_for_status()
|
|
|
|
def start_patch_builder(self) -> PatchBuilder:
|
|
self._patch_builder = PatchBuilder(self)
|
|
return self._patch_builder
|
|
|
|
def apply_diff(self, diff: Union[str, bytes]):
|
|
files = {
|
|
':diff': (
|
|
None,
|
|
diff,
|
|
'text/plain; charset=utf-8'
|
|
)
|
|
}
|
|
# todo check for exception
|
|
resp = self._session.post(self._data_root, files=files)
|
|
resp.raise_for_status()
|