mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-02-17 23:46:23 +00:00
233 lines
6.4 KiB
JavaScript
233 lines
6.4 KiB
JavaScript
import {
|
|
DAVNamespace,
|
|
davRequest,
|
|
propfind
|
|
} from 'tsdav'
|
|
import ICAL from 'ical.js'
|
|
|
|
class TestUtility {
|
|
constructor(webdav) {
|
|
this.webdav = webdav
|
|
this.userInfo = {}
|
|
}
|
|
|
|
async fetchUserInfo(login) {
|
|
if (!this.userInfo[login]) {
|
|
const results = await propfind({
|
|
url: `${this.webdav.serverUrl}/SOGo/dav/${login}/`,
|
|
props: [
|
|
{ name: 'displayname', namespace: DAVNamespace.DAV },
|
|
{ name: 'calendar-timezone', namespace: DAVNamespace.CALDAV },
|
|
{ name: 'calendar-user-address-set', namespace: DAVNamespace.CALDAV }
|
|
],
|
|
depth: '0',
|
|
headers: this.webdav.headers,
|
|
})
|
|
if (results.length != 1) {
|
|
throw new Error(`Unexpected number of status in profind for user ${login}`)
|
|
}
|
|
|
|
const response = results[0]
|
|
if (!response.props.calendarUserAddressSet.href.length) {
|
|
throw new Error(`No address found in calendar-user-address-set for user ${login}`)
|
|
}
|
|
|
|
let displayname = response.props.displayname || ''
|
|
let email = response.props.calendarUserAddressSet.href[0]
|
|
let timezone = response.props.calendarTimezone || ''
|
|
this.userInfo[login] = { displayname, email, timezone }
|
|
}
|
|
return this.userInfo[login]
|
|
}
|
|
|
|
formatTemplate(template, vars) {
|
|
var s = template
|
|
Object.keys(vars).forEach(k => {
|
|
s = s.replace(new RegExp(`%\\(${k}\\)`, 'g'), vars[k])
|
|
})
|
|
s = s.replace(/%\([^\)]+\)/g, '') // clear all reminding placeholders
|
|
return s;
|
|
}
|
|
|
|
camelCase(snakeCase) {
|
|
return snakeCase.replace(/(?:^\w|[A-Z]|\b\w)/g, (char, i) =>
|
|
i === 0 ? char.toLowerCase() : char.toUpperCase(),
|
|
)
|
|
.replace(/[\s\-_]+/g, '')
|
|
}
|
|
|
|
setupRights(resource, username, rights) {
|
|
const action = (typeof rights == 'undefined') ? 'remove-user' : 'set-roles'
|
|
return davRequest({
|
|
url: `${this.webdav.serverUrl}${resource}`,
|
|
init: {
|
|
method: 'POST',
|
|
headers: this.webdav.headers,
|
|
body: {
|
|
'acl-query': {
|
|
_attributes: { xmlns: 'urn:inverse:params:xml:ns:inverse-dav' },
|
|
[action]: {
|
|
_attributes: { user: username.replace('<', '<').replace('>', '>') },
|
|
...rights
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
setupCalendarRights(resource, username, rights) {
|
|
let sogoRights = {}
|
|
if (rights.c)
|
|
sogoRights.ObjectCreator = {}
|
|
if (rights.d)
|
|
sogoRights.ObjectEraser = {}
|
|
|
|
const classes = {
|
|
pu: 'Public',
|
|
pr: 'Private',
|
|
co: 'Confidential'
|
|
}
|
|
const rightsTable = {
|
|
v: 'Viewer',
|
|
d: 'DAndTViewer',
|
|
m: 'Modifier',
|
|
r: 'Responder'
|
|
}
|
|
Object.keys(classes).forEach(c => {
|
|
if (rights[c]) {
|
|
const right = rights[c]
|
|
const sogoRight = `${classes[c]}${rightsTable[right]}`
|
|
sogoRights[sogoRight] = {}
|
|
}
|
|
})
|
|
|
|
return this.setupRights(resource, username, sogoRights)
|
|
}
|
|
|
|
setupAddressBookRights(resource, username, rights) {
|
|
let sogoRights = {}
|
|
|
|
const rightsTable = {
|
|
c: 'ObjectCreator',
|
|
d: 'ObjectEraser',
|
|
v: 'ObjectViewer',
|
|
e: 'ObjectEditor'
|
|
}
|
|
Object.keys(rights).forEach(r => {
|
|
if (rightsTable[r]) {
|
|
sogoRights[rightsTable[r]] = {}
|
|
}
|
|
})
|
|
|
|
return this.setupRights(resource, username, sogoRights)
|
|
}
|
|
|
|
_subscriptionOperation(resource, subscribers, operation) {
|
|
return davRequest({
|
|
url: `${this.webdav.serverUrl}${resource}`,
|
|
init: {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/xml; charset="utf-8"',
|
|
...this.webdav.headers
|
|
},
|
|
body: {
|
|
[operation]: {
|
|
_attributes: {
|
|
xmlns: 'urn:inverse:params:xml:ns:inverse-dav',
|
|
users: subscribers.join(',')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
subscribe(resource, subscribers) {
|
|
return this._subscriptionOperation(resource, subscribers, 'subscribe')
|
|
}
|
|
|
|
unsubscribe(resource, subscribers) {
|
|
return this._subscriptionOperation(resource, subscribers, 'unsubscribe')
|
|
}
|
|
|
|
versitDict(component) {
|
|
const comp = ICAL.Component.fromString(component)
|
|
let props = {}
|
|
|
|
for (const prop of comp.getAllProperties()) {
|
|
props[prop.name] = prop.toICALString()
|
|
}
|
|
for (const subcomp of comp.getAllSubcomponents()) {
|
|
for (const prop of subcomp.getAllProperties()) {
|
|
props[prop.name] = prop.toICALString()
|
|
}
|
|
}
|
|
return props
|
|
}
|
|
|
|
componentsAreEqual(comp1, comp2) {
|
|
const props1 = this.versitDict(comp1)
|
|
const props2 = this.versitDict(comp2)
|
|
for (const prop of Object.keys(props1)) {
|
|
if (props1[prop] != props2[prop]) {
|
|
console.debug(`Difference detected in ${prop}:\n\t1: ${props1[prop]}\n\t2: ${props2[prop]}`)
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
createDateTimeProperty(propertyName, dateObject = new Date()) {
|
|
let property = new ICAL.Property(propertyName)
|
|
property.setParameter('tzid', 'America/Toronto')
|
|
property.setValue(ICAL.Time.fromJSDate(dateObject))
|
|
|
|
return property
|
|
}
|
|
|
|
createCalendar(summary = 'test event', uid = 'test', transp = 'OPAQUE') {
|
|
const vcalendar = new ICAL.Component('vcalendar')
|
|
const vevent = new ICAL.Component('vevent')
|
|
const now = new Date()
|
|
const later = new Date(now.getTime() + 1000*60*60) // event lasts one hour
|
|
const vtimezone = ICAL.Component.fromString(`BEGIN:VTIMEZONE
|
|
TZID:America/Toronto
|
|
LAST-MODIFIED:20210303T135712Z
|
|
X-LIC-LOCATION:America/Toronto
|
|
BEGIN:DAYLIGHT
|
|
TZNAME:EDT
|
|
TZOFFSETFROM:-0500
|
|
TZOFFSETTO:-0400
|
|
DTSTART:19700308T020000
|
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
|
END:DAYLIGHT
|
|
BEGIN:STANDARD
|
|
TZNAME:EST
|
|
TZOFFSETFROM:-0400
|
|
TZOFFSETTO:-0500
|
|
DTSTART:19701101T020000
|
|
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
|
END:STANDARD
|
|
END:VTIMEZONE`)
|
|
|
|
vcalendar.addSubcomponent(vtimezone)
|
|
vcalendar.addSubcomponent(vevent)
|
|
vevent.addPropertyWithValue('uid', uid)
|
|
vevent.addPropertyWithValue('summary', summary)
|
|
vevent.addPropertyWithValue('transp', transp)
|
|
vevent.addProperty(this.createDateTimeProperty('dtstart', now))
|
|
vevent.addProperty(this.createDateTimeProperty('dtend', later))
|
|
vevent.addProperty(this.createDateTimeProperty('dtstamp', now))
|
|
vevent.addProperty(this.createDateTimeProperty('last-modified', now))
|
|
vevent.addProperty(this.createDateTimeProperty('created', now))
|
|
vevent.addPropertyWithValue('class', 'PUBLIC')
|
|
vevent.addPropertyWithValue('sequence', '0')
|
|
|
|
return vcalendar
|
|
}
|
|
|
|
}
|
|
|
|
export default TestUtility |