sogo/Tests/lib/WebDAV.js

432 lines
11 KiB
JavaScript

import {
DAVNamespace,
DAVNamespaceShorthandMap,
davRequest,
deleteObject,
getBasicAuthHeaders,
propfind,
syncCollection,
calendarMultiGet,
createCalendarObject,
makeCalendar,
createVCard
} from 'tsdav'
import { formatProps, getDAVAttribute } from 'tsdav/dist/util/requestHelpers';
import { makeCollection } from 'tsdav/dist/collection';
import convert from 'xml-js'
import { fetch } from 'cross-fetch'
import config from './config'
const DAVInverse = 'urn:inverse:params:xml:ns:inverse-dav'
const DAVInverseShort = 'i'
export { DAVInverse, DAVInverseShort }
class WebDAV {
constructor(un, pw) {
this.serverUrl = `http://${config.hostname}:${config.port}`
if (un && pw) {
this.headers = getBasicAuthHeaders({
username: un,
password: pw
})
}
else {
this.headers = {}
}
}
deleteObject(resource) {
return deleteObject({
url: this.serverUrl + resource,
headers: this.headers
})
}
makeCalendar(resource) {
return makeCalendar({
url: this.serverUrl + resource,
headers: this.headers
})
}
createCalendarObject(resource, filename, calendar) {
return createCalendarObject({
headers: this.headers,
calendar: { url: this.serverUrl + resource }, // DAVCalendar
filename: filename,
iCalString: calendar
})
}
postCaldav(resource, vcalendar, originator, recipients) {
let localHeaders = { 'content-type': 'text/calendar; charset=utf-8'}
if (originator)
localHeaders.originator = originator
if (recipients && recipients.length > 0)
localHeaders.recipients = recipients.join(',')
return fetch(this.serverUrl + resource, {
method: 'POST',
body: vcalendar,
headers: { ...this.headers, ...localHeaders }
})
}
getObject(resource, filename) {
let url
if (resource.match(/^http/))
url = resource
else
url = this.serverUrl + resource
if (filename)
url += filename
return davRequest({
url,
init: {
method: 'GET',
headers: this.headers,
body: null
},
convertIncoming: false
})
}
propfindWebdav(resource, properties, namespace = DAVNamespace.DAV, headers = {}) {
const nsShort = DAVNamespaceShorthandMap[namespace] || DAVInverseShort
const formattedProperties = properties.map(p => {
return { [`${nsShort}:${p}`]: '' }
})
if (typeof headers.depth == 'undefined') {
headers.depth = new String(0)
}
return davRequest({
url: this.serverUrl + resource,
init: {
method: 'PROPFIND',
headers: { ...this.headers, ...headers },
namespace: DAVNamespaceShorthandMap[DAVNamespace.DAV],
body: {
propfind: {
_attributes: {
...getDAVAttribute([DAVNamespace.DAV]),
[`xmlns:${nsShort}`]: namespace
},
prop: formattedProperties
}
}
}
})
}
propfindWebdavRaw(resource, properties, headers = {}) {
const namespace = DAVNamespaceShorthandMap[DAVNamespace.DAV]
const formattedProperties = properties.map(prop => {
return { [`${namespace}:${prop}`]: '' }
})
let xmlBody = convert.js2xml(
{
propfind: {
_attributes: getDAVAttribute([DAVNamespace.DAV]),
prop: formattedProperties
}
},
{
compact: true,
spaces: 2,
elementNameFn: (name) => {
// add namespace to all keys without namespace
if (!/^.+:.+/.test(name)) {
return `${namespace}:${name}`;
}
return name;
},
}
)
return fetch(this.serverUrl + resource, {
headers: {
'Content-Type': 'application/xml; charset="utf-8"',
...headers,
...this.headers
},
method: 'PROPFIND',
body: xmlBody
})
}
propfindEvent(resource) {
return propfind({
url: this.serverUrl + resource,
headers: this.headers,
depth: '1',
props: [
{ name: 'calendar-data', namespace: DAVNamespace.CALDAV }
]
})
}
calendarMultiGet(resource, filename) {
return calendarMultiGet({
url: this.serverUrl + resource,
headers: this.headers,
props: [
{ name: 'calendar-data', namespace: DAVNamespace.CALDAV },
],
objectUrls: [ this.serverUrl + resource + filename ]
})
}
principalCollectionSet(resource = '/SOGo/dav') {
return propfind({
url: this.serverUrl + resource,
depth: '0',
props: [{ name: 'principal-collection-set', namespace: DAVNamespace.DAV }],
headers: this.headers
})
}
propfindURL(resource = '/SOGo/dav') {
return propfind({
url: this.serverUrl + resource,
depth: '1',
props: [
{ name: 'displayname', namespace: DAVNamespace.DAV },
{ name: 'resourcetype', namespace: DAVNamespace.DAV }
],
headers: this.headers
})
}
propfindCollection(resource) {
return propfind({
url: this.serverUrl + resource,
headers: this.headers
})
}
principalPropertySearch(resource) {
return davRequest({
url: `${this.serverUrl}/SOGo/dav`,
init: {
method: 'REPORT',
namespace: DAVNamespaceShorthandMap[DAVNamespace.DAV],
headers: this.headers,
body: {
'principal-property-search': {
_attributes: getDAVAttribute([
DAVNamespace.CALDAV,
DAVNamespace.DAV,
]),
'property-search': [
{
[`${DAVNamespaceShorthandMap[DAVNamespace.DAV]}:prop`]: formatProps([{ name: 'calendar-home-set', namespace: DAVNamespace.CALDAV }]),
'match': resource
}
],
[`${DAVNamespaceShorthandMap[DAVNamespace.DAV]}:prop`]: formatProps([{ name: 'displayname', namespace: DAVNamespace.DAV }])
}
}
},
})
}
// http://tools.ietf.org/html/rfc3253.html#section-3.8
expendProperty(resource, properties) {
return davRequest({
url: this.serverUrl + resource,
init: {
method: 'REPORT',
namespace: DAVNamespaceShorthandMap[DAVNamespace.DAV],
headers: this.headers,
body: {
'expand-property': {
_attributes: getDAVAttribute([
DAVNamespace.DAV,
]),
[`${DAVNamespaceShorthandMap[DAVNamespace.DAV]}:property`]: properties
}
}
},
})
}
syncColletion(resource) {
return davRequest({
url: this.serverUrl + resource,
init: {
method: 'REPORT',
namespace: DAVNamespaceShorthandMap[DAVNamespace.DAV],
headers: this.headers,
body: {
'sync-collection': {
_attributes: getDAVAttribute([
DAVNamespace.CALDAV,
DAVNamespace.DAV
]),
[`${DAVNamespaceShorthandMap[DAVNamespace.DAV]}:prop`]: formatProps([{ name: 'calendar-data', namespace: DAVNamespace.CALDAV }]),
}
}
},
})
}
syncQuery(resource, token = '', properties) {
const formattedProperties = properties.map(p => { return { name: p, namespace: DAVNamespace.DAV } })
return syncCollection({
url: this.serverUrl + resource,
props: formattedProperties,
syncLevel: 1,
syncToken: token,
headers: this.headers
})
}
propfindCaldav(resource, properties, depth = 0, parseOutgoing = true) {
const formattedProperties = properties.map(p => { return { name: p, namespace: DAVNamespace.CALDAV } })
return davRequest({
url: this.serverUrl + resource,
init: {
method: 'PROPFIND',
headers: { ...this.headers, depth: new String(depth) },
namespace: DAVNamespaceShorthandMap[DAVNamespace.DAV],
body: {
propfind: {
_attributes: getDAVAttribute([
DAVNamespace.CALDAV,
DAVNamespace.CALDAV_APPLE,
DAVNamespace.CALENDAR_SERVER,
DAVNamespace.CARDDAV,
DAVNamespace.DAV
]),
prop: formattedProperties.length ? formatProps(formattedProperties) : null,
}
}
},
parseOutgoing
})
}
proppatchCaldav(resource, properties, headers = {}) {
const formattedProperties = Object.keys(properties).map(p => {
return { name: p, namespace: DAVNamespace.CALDAV, value: properties[p] }
})
return davRequest({
url: this.serverUrl + resource,
init: {
method: 'PROPPATCH',
headers: { ...this.headers, ...headers },
namespace: DAVNamespaceShorthandMap[DAVNamespace.DAV],
body: {
propertyupdate: {
_attributes: getDAVAttribute([
DAVNamespace.CALDAV,
DAVNamespace.CALDAV_APPLE,
DAVNamespace.CALENDAR_SERVER,
DAVNamespace.CARDDAV,
DAVNamespace.DAV
]),
set: {
prop: formatProps(formattedProperties)
}
}
}
}
// parseOutgoing
})
}
proppatchWebdav(resource, properties, namespace = DAVNamespace.DAV, headers = {}) {
const nsShort = DAVNamespaceShorthandMap[namespace] || DAVInverseShort
const formattedProperties = Object.keys(properties).map(p => {
if (Array.isArray(properties[p])) {
return { [`${nsShort}:${p}`]: properties[p].map(pp => {
const [ key ] = Object.keys(pp)
return { [`${nsShort}:${key}`]: pp[key] || '' }
})}
}
return { [`${nsShort}:${p}`]: properties[p] || '' }
})
if (typeof headers.depth == 'undefined') {
headers.depth = new String(0)
}
return davRequest({
url: this.serverUrl + resource,
init: {
method: 'PROPPATCH',
headers: { ...this.headers, ...headers },
namespace: DAVNamespaceShorthandMap[DAVNamespace.DAV],
body: {
propertyupdate: {
_attributes: {
...getDAVAttribute([DAVNamespace.DAV]),
[`xmlns:${nsShort}`]: namespace
},
set: {
prop: formattedProperties
}
}
}
}
})
}
currentUserPrivilegeSet(resource) {
return propfind({
url: this.serverUrl + resource,
depth: '0',
props: [
{ name: 'current-user-privilege-set', namespace: DAVNamespace.DAV }
],
headers: this.headers
})
}
makeCollection(resource) {
return makeCollection({
url: this.serverUrl + resource,
headers: this.headers
});
}
getCard(resource, filename) {
return davRequest({
url: this.serverUrl + resource + filename,
init: {
method: 'GET',
headers: this.headers,
body: null
},
convertIncoming: false
})
}
createVCard(resource, filename, card) {
return createVCard({
headers: this.headers,
addressBook: { url: this.serverUrl + resource }, // DAVAddressBook
filename,
vCardString: card
})
}
options(resource) {
return davRequest({
url: this.serverUrl + resource,
init: {
method: 'OPTIONS',
headers: this.headers,
body: null
},
convertIncoming: false
})
}
}
export default WebDAV