UI: Retrieve permissions when loading collections
This commit is contained in:
@@ -51,7 +51,8 @@ export function get_principal(user, password, callback) {
|
|||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
""), null);
|
"",
|
||||||
|
[]), null,);
|
||||||
} else {
|
} else {
|
||||||
callback(null, "No valid XML received")
|
callback(null, "No valid XML received")
|
||||||
}
|
}
|
||||||
@@ -94,81 +95,20 @@ export function get_collections(user, password, collection, callback) {
|
|||||||
let response_query = "*|multistatus:root > *|response";
|
let response_query = "*|multistatus:root > *|response";
|
||||||
let responses = xml.querySelectorAll(response_query);
|
let responses = xml.querySelectorAll(response_query);
|
||||||
for (let i = 0; i < responses.length; i++) {
|
for (let i = 0; i < responses.length; i++) {
|
||||||
let response = responses[i];
|
let parsedCollection = _parse_collection(responses[i], collection.href);
|
||||||
let href_element = response.querySelector(response_query + " > *|href");
|
if (parsedCollection) {
|
||||||
let resourcetype_query = response_query + " > *|propstat > *|prop > *|resourcetype";
|
collections.push(parsedCollection);
|
||||||
let resourcetype_element = response.querySelector(resourcetype_query);
|
|
||||||
let displayname_element = response.querySelector(response_query + " > *|propstat > *|prop > *|displayname");
|
|
||||||
let calendarcolor_element = response.querySelector(response_query + " > *|propstat > *|prop > *|calendar-color");
|
|
||||||
let addressbookcolor_element = response.querySelector(response_query + " > *|propstat > *|prop > *|addressbook-color");
|
|
||||||
let calendardesc_element = response.querySelector(response_query + " > *|propstat > *|prop > *|calendar-description");
|
|
||||||
let addressbookdesc_element = response.querySelector(response_query + " > *|propstat > *|prop > *|addressbook-description");
|
|
||||||
let contentcount_element = response.querySelector(response_query + " > *|propstat > *|prop > *|getcontentcount");
|
|
||||||
let contentlength_element = response.querySelector(response_query + " > *|propstat > *|prop > *|getcontentlength");
|
|
||||||
let webcalsource_element = response.querySelector(response_query + " > *|propstat > *|prop > *|source");
|
|
||||||
let components_query = response_query + " > *|propstat > *|prop > *|supported-calendar-component-set";
|
|
||||||
let components_element = response.querySelector(components_query);
|
|
||||||
let href = href_element ? href_element.textContent : "";
|
|
||||||
let displayname = displayname_element ? displayname_element.textContent : "";
|
|
||||||
let type = "";
|
|
||||||
let color = "";
|
|
||||||
let description = "";
|
|
||||||
let source = "";
|
|
||||||
let count = 0;
|
|
||||||
let size = 0;
|
|
||||||
if (resourcetype_element) {
|
|
||||||
if (resourcetype_element.querySelector(resourcetype_query + " > *|addressbook")) {
|
|
||||||
type = CollectionType.ADDRESSBOOK;
|
|
||||||
color = addressbookcolor_element ? addressbookcolor_element.textContent : "";
|
|
||||||
description = addressbookdesc_element ? addressbookdesc_element.textContent : "";
|
|
||||||
count = contentcount_element ? parseInt(contentcount_element.textContent) : 0;
|
|
||||||
size = contentlength_element ? parseInt(contentlength_element.textContent) : 0;
|
|
||||||
} else if (resourcetype_element.querySelector(resourcetype_query + " > *|subscribed")) {
|
|
||||||
type = CollectionType.WEBCAL;
|
|
||||||
source = webcalsource_element ? webcalsource_element.textContent : "";
|
|
||||||
color = calendarcolor_element ? calendarcolor_element.textContent : "";
|
|
||||||
description = calendardesc_element ? calendardesc_element.textContent : "";
|
|
||||||
} else if (resourcetype_element.querySelector(resourcetype_query + " > *|calendar")) {
|
|
||||||
if (components_element) {
|
|
||||||
if (components_element.querySelector(components_query + " > *|comp[name=VEVENT]")) {
|
|
||||||
type = CollectionType.union(type, CollectionType.CALENDAR);
|
|
||||||
}
|
|
||||||
if (components_element.querySelector(components_query + " > *|comp[name=VJOURNAL]")) {
|
|
||||||
type = CollectionType.union(type, CollectionType.JOURNAL);
|
|
||||||
}
|
|
||||||
if (components_element.querySelector(components_query + " > *|comp[name=VTODO]")) {
|
|
||||||
type = CollectionType.union(type, CollectionType.TASKS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
color = calendarcolor_element ? calendarcolor_element.textContent : "";
|
|
||||||
description = calendardesc_element ? calendardesc_element.textContent : "";
|
|
||||||
count = contentcount_element ? parseInt(contentcount_element.textContent) : 0;
|
|
||||||
size = contentlength_element ? parseInt(contentlength_element.textContent) : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let sane_color = color.trim();
|
|
||||||
if (sane_color) {
|
|
||||||
let color_match = COLOR_RE.exec(sane_color);
|
|
||||||
if (color_match) {
|
|
||||||
sane_color = color_match[1];
|
|
||||||
} else {
|
|
||||||
sane_color = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (href.substr(-1) === "/" && href !== collection.href && type) {
|
|
||||||
collections.push(new Collection(href, type, displayname, description, sane_color, count, size, source));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
collections.sort(function (a, b) {
|
collections.sort(function (a, b) {
|
||||||
/** @type {string} */ let ca = a.displayname || a.href;
|
/** @type {string} */ let ca = a.displayname || a.href;
|
||||||
/** @type {string} */ let cb = b.displayname || b.href;
|
/** @type {string} */ let cb = b.displayname || b.href;
|
||||||
return ca.localeCompare(cb);
|
return ca.localeCompare(cb);
|
||||||
});
|
});
|
||||||
callback(collections, null);
|
callback(collections, null);
|
||||||
} else {
|
} else {
|
||||||
callback(null, "No valid XML received")
|
callback(null, "No valid XML received");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
callback(null, to_error_message(request));
|
callback(null, to_error_message(request));
|
||||||
}
|
}
|
||||||
@@ -194,11 +134,136 @@ export function get_collections(user, password, collection, callback) {
|
|||||||
'<CS:source />' +
|
'<CS:source />' +
|
||||||
'<RADICALE:getcontentcount />' +
|
'<RADICALE:getcontentcount />' +
|
||||||
'<getcontentlength />' +
|
'<getcontentlength />' +
|
||||||
|
'<current-user-privilege-set />' +
|
||||||
'</prop>' +
|
'</prop>' +
|
||||||
'</propfind>');
|
'</propfind>');
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses permissions from the current-user-privilege-set element.
|
||||||
|
* @param {Element|null} current_user_privilege_set_element
|
||||||
|
* @returns {Array<string>}
|
||||||
|
*/
|
||||||
|
function _parse_permissions(current_user_privilege_set_element) {
|
||||||
|
if (!current_user_privilege_set_element) return [];
|
||||||
|
let permissions = [];
|
||||||
|
let privileges = current_user_privilege_set_element.querySelectorAll("*|privilege");
|
||||||
|
for (let j = 0; j < privileges.length; j++) {
|
||||||
|
let privilege = privileges[j];
|
||||||
|
let privilege_children = privilege.children;
|
||||||
|
for (let k = 0; k < privilege_children.length; k++) {
|
||||||
|
let child = privilege_children[k];
|
||||||
|
let prefix = "D:";
|
||||||
|
if (child.namespaceURI) {
|
||||||
|
if (child.namespaceURI === "DAV:") {
|
||||||
|
prefix = "D:";
|
||||||
|
} else if (child.namespaceURI === "http://radicale.org/ns/") {
|
||||||
|
prefix = "RADICALE:";
|
||||||
|
} else {
|
||||||
|
prefix = child.namespaceURI + ":";
|
||||||
|
}
|
||||||
|
} else if (child.nodeName.includes(":")) {
|
||||||
|
prefix = ""; // nodeName already contains prefix
|
||||||
|
}
|
||||||
|
let permName = child.localName || child.nodeName;
|
||||||
|
if (!permName.includes(":")) {
|
||||||
|
permName = prefix + permName;
|
||||||
|
}
|
||||||
|
permissions.push(permName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a single response element into a Collection object.
|
||||||
|
* @param {Element} response
|
||||||
|
* @param {string} collection_href
|
||||||
|
* @returns {Collection|null}
|
||||||
|
*/
|
||||||
|
function _parse_collection(response, collection_href) {
|
||||||
|
let href_element = response.querySelector("*|href");
|
||||||
|
let current_user_privilege_set_element = response.querySelector("*|propstat > *|prop > *|current-user-privilege-set");
|
||||||
|
let resourcetype_element = response.querySelector("*|propstat > *|prop > *|resourcetype");
|
||||||
|
let displayname_element = response.querySelector("*|propstat > *|prop > *|displayname");
|
||||||
|
|
||||||
|
let href = href_element ? href_element.textContent : "";
|
||||||
|
let displayname = displayname_element ? displayname_element.textContent : "";
|
||||||
|
let type = "";
|
||||||
|
let color = "";
|
||||||
|
let description = "";
|
||||||
|
let source = "";
|
||||||
|
let count = 0;
|
||||||
|
let size = 0;
|
||||||
|
let permissions = _parse_permissions(current_user_privilege_set_element);
|
||||||
|
|
||||||
|
if (resourcetype_element) {
|
||||||
|
if (resourcetype_element.querySelector("*|addressbook")) {
|
||||||
|
type = CollectionType.ADDRESSBOOK;
|
||||||
|
let addressbookcolor_element = response.querySelector("*|propstat > *|prop > *|addressbook-color");
|
||||||
|
let addressbookdesc_element = response.querySelector("*|propstat > *|prop > *|addressbook-description");
|
||||||
|
let contentcount_element = response.querySelector("*|propstat > *|prop > *|getcontentcount");
|
||||||
|
let contentlength_element = response.querySelector("*|propstat > *|prop > *|getcontentlength");
|
||||||
|
|
||||||
|
color = addressbookcolor_element ? addressbookcolor_element.textContent : "";
|
||||||
|
description = addressbookdesc_element ? addressbookdesc_element.textContent : "";
|
||||||
|
count = contentcount_element ? parseInt(contentcount_element.textContent, 10) : 0;
|
||||||
|
size = contentlength_element ? parseInt(contentlength_element.textContent, 10) : 0;
|
||||||
|
if (isNaN(count)) count = 0;
|
||||||
|
if (isNaN(size)) size = 0;
|
||||||
|
} else if (resourcetype_element.querySelector("*|subscribed")) {
|
||||||
|
type = CollectionType.WEBCAL;
|
||||||
|
let webcalsource_element = response.querySelector("*|propstat > *|prop > *|source");
|
||||||
|
let calendarcolor_element = response.querySelector("*|propstat > *|prop > *|calendar-color");
|
||||||
|
let calendardesc_element = response.querySelector("*|propstat > *|prop > *|calendar-description");
|
||||||
|
|
||||||
|
source = webcalsource_element ? webcalsource_element.textContent : "";
|
||||||
|
color = calendarcolor_element ? calendarcolor_element.textContent : "";
|
||||||
|
description = calendardesc_element ? calendardesc_element.textContent : "";
|
||||||
|
} else if (resourcetype_element.querySelector("*|calendar")) {
|
||||||
|
let components_element = response.querySelector("*|propstat > *|prop > *|supported-calendar-component-set");
|
||||||
|
if (components_element) {
|
||||||
|
if (components_element.querySelector("*|comp[name=VEVENT]")) {
|
||||||
|
type = CollectionType.union(type, CollectionType.CALENDAR);
|
||||||
|
}
|
||||||
|
if (components_element.querySelector("*|comp[name=VJOURNAL]")) {
|
||||||
|
type = CollectionType.union(type, CollectionType.JOURNAL);
|
||||||
|
}
|
||||||
|
if (components_element.querySelector("*|comp[name=VTODO]")) {
|
||||||
|
type = CollectionType.union(type, CollectionType.TASKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let calendarcolor_element = response.querySelector("*|propstat > *|prop > *|calendar-color");
|
||||||
|
let calendardesc_element = response.querySelector("*|propstat > *|prop > *|calendar-description");
|
||||||
|
let contentcount_element = response.querySelector("*|propstat > *|prop > *|getcontentcount");
|
||||||
|
let contentlength_element = response.querySelector("*|propstat > *|prop > *|getcontentlength");
|
||||||
|
|
||||||
|
color = calendarcolor_element ? calendarcolor_element.textContent : "";
|
||||||
|
description = calendardesc_element ? calendardesc_element.textContent : "";
|
||||||
|
count = contentcount_element ? parseInt(contentcount_element.textContent, 10) : 0;
|
||||||
|
size = contentlength_element ? parseInt(contentlength_element.textContent, 10) : 0;
|
||||||
|
if (isNaN(count)) count = 0;
|
||||||
|
if (isNaN(size)) size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let sane_color = color.trim();
|
||||||
|
if (sane_color) {
|
||||||
|
let color_match = COLOR_RE.exec(sane_color);
|
||||||
|
if (color_match) {
|
||||||
|
sane_color = color_match[1];
|
||||||
|
} else {
|
||||||
|
sane_color = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (href.endsWith("/") && href !== collection_href && type) {
|
||||||
|
return new Collection(href, type, displayname, description, sane_color, count, size, source, permissions);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} user
|
* @param {string} user
|
||||||
* @param {?string} password
|
* @param {?string} password
|
||||||
|
|||||||
@@ -110,8 +110,9 @@ export class Collection {
|
|||||||
* @param {number} contentcount
|
* @param {number} contentcount
|
||||||
* @param {number} size
|
* @param {number} size
|
||||||
* @param {string} source
|
* @param {string} source
|
||||||
|
* @param {Array<string>} permissions
|
||||||
*/
|
*/
|
||||||
constructor(href, type, displayname, description, color, contentcount, size, source) {
|
constructor(href, type, displayname, description, color, contentcount, size, source, permissions) {
|
||||||
this.href = href;
|
this.href = href;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.displayname = displayname;
|
this.displayname = displayname;
|
||||||
@@ -120,5 +121,6 @@ export class Collection {
|
|||||||
this.source = source;
|
this.source = source;
|
||||||
this.contentcount = contentcount;
|
this.contentcount = contentcount;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
this.permissions = permissions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ export class CreateEditCollectionScene {
|
|||||||
}
|
}
|
||||||
let loading_scene = new LoadingScene();
|
let loading_scene = new LoadingScene();
|
||||||
push_scene(loading_scene);
|
push_scene(loading_scene);
|
||||||
let collection = new Collection(this._href, this._type, this._displayname, this._description, sane_color, 0, 0, this._source);
|
let collection = new Collection(this._href, this._type, this._displayname, this._description, sane_color, 0, 0, this._source, []);
|
||||||
let callback = (/** @type {?string} */ error1) => {
|
let callback = (/** @type {?string} */ error1) => {
|
||||||
if (!is_current_scene(loading_scene)) {
|
if (!is_current_scene(loading_scene)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user