mirror of https://github.com/xwiki-labs/cryptpad
Import calendars from URL and upgrade if needed
This commit is contained in:
parent
67fae22156
commit
63581e2cf3
|
@ -65,6 +65,7 @@ Messages.calendar_deleteOwned = " It will still be visible for the users it has
|
|||
Messages.calendar_errorNoCalendar = "No editable calendar selected!";
|
||||
Messages.calendar_myCalendars = "My calendars";
|
||||
Messages.calendar_tempCalendar = "Temp calendar";
|
||||
Messages.calendar_import = "Import to my calendars";
|
||||
|
||||
var onCalendarsUpdate = Util.mkEvent();
|
||||
|
||||
|
@ -86,6 +87,12 @@ Messages.calendar_tempCalendar = "Temp calendar";
|
|||
cb(null, obj);
|
||||
});
|
||||
};
|
||||
var importCalendar = function (data, cb) {
|
||||
APP.module.execCommand('IMPORT', data, function (obj) {
|
||||
if (obj && obj.error) { return void cb(obj.error); }
|
||||
cb(null, obj);
|
||||
});
|
||||
};
|
||||
var newEvent = function (data, cb) {
|
||||
var start = data.start;
|
||||
var end = data.end;
|
||||
|
@ -307,50 +314,83 @@ Messages.calendar_tempCalendar = "Temp calendar";
|
|||
UI.openCustomModal(m);
|
||||
};
|
||||
|
||||
var isReadOnly = function (id, teamId) {
|
||||
var data = APP.calendars[id];
|
||||
return data.readOnly || (data.roTeams && data.roTeams.indexOf(teamId) !== -1);
|
||||
};
|
||||
var makeEditDropdown = function (id, teamId) {
|
||||
var options = [{
|
||||
tag: 'a',
|
||||
attributes: {
|
||||
'class': 'fa fa-pencil',
|
||||
},
|
||||
content: h('span', Messages.tag_edit),
|
||||
action: function (e) {
|
||||
e.stopPropagation();
|
||||
editCalendar(id);
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
tag: 'a',
|
||||
attributes: {
|
||||
'class': 'fa fa-shhare-alt',
|
||||
},
|
||||
content: h('span', Messages.shareButton),
|
||||
action: function (e) {
|
||||
e.stopPropagation();
|
||||
var friends = common.getFriends();
|
||||
var cal = APP.calendars[id];
|
||||
var title = Util.find(cal, ['content', 'metadata', 'title']);
|
||||
var color = Util.find(cal, ['content', 'metadata', 'color']);
|
||||
Share.getShareModal(common, {
|
||||
teamId: teamId === 1 ? undefined : teamId,
|
||||
origin: APP.origin,
|
||||
pathname: "/calendar/",
|
||||
friends: friends,
|
||||
title: title,
|
||||
password: cal.password, // XXX support passwords
|
||||
calendar: {
|
||||
title: title,
|
||||
color: color,
|
||||
channel: id,
|
||||
},
|
||||
common: common,
|
||||
hashes: cal.hashes
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}];
|
||||
var options = [];
|
||||
var privateData = metadataMgr.getPrivateData();
|
||||
var cantRemove = teamId === 0 || (teamId !== 1 && privateData.teams[teamId].viewer);
|
||||
var data = APP.calendars[id];
|
||||
if (!data.readOnly) {
|
||||
options.push({
|
||||
tag: 'a',
|
||||
attributes: {
|
||||
'class': 'fa fa-pencil',
|
||||
},
|
||||
content: h('span', Messages.tag_edit),
|
||||
action: function (e) {
|
||||
e.stopPropagation();
|
||||
editCalendar(id);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (data.teams.indexOf(1) === -1 || teamId === 0) {
|
||||
options.push({
|
||||
tag: 'a',
|
||||
attributes: {
|
||||
'class': 'fa fa-clone',
|
||||
},
|
||||
content: h('span', Messages.calendar_import),
|
||||
action: function (e) {
|
||||
e.stopPropagation();
|
||||
importCalendar({
|
||||
id: id,
|
||||
teamId: teamId
|
||||
}, function (obj) {
|
||||
if (obj && obj.error) {
|
||||
console.error(obj.error);
|
||||
return void UI.warn(obj.error);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!data.restricted) {
|
||||
options.push({
|
||||
tag: 'a',
|
||||
attributes: {
|
||||
'class': 'fa fa-shhare-alt',
|
||||
},
|
||||
content: h('span', Messages.shareButton),
|
||||
action: function (e) {
|
||||
e.stopPropagation();
|
||||
var friends = common.getFriends();
|
||||
var cal = APP.calendars[id];
|
||||
var title = Util.find(cal, ['content', 'metadata', 'title']);
|
||||
var color = Util.find(cal, ['content', 'metadata', 'color']);
|
||||
Share.getShareModal(common, {
|
||||
teamId: teamId === 1 ? undefined : teamId,
|
||||
origin: APP.origin,
|
||||
pathname: "/calendar/",
|
||||
friends: friends,
|
||||
title: title,
|
||||
password: cal.password, // XXX support passwords
|
||||
calendar: {
|
||||
title: title,
|
||||
color: color,
|
||||
channel: id,
|
||||
},
|
||||
common: common,
|
||||
hashes: cal.hashes
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!cantRemove) {
|
||||
options.push({
|
||||
tag: 'a',
|
||||
|
@ -397,7 +437,7 @@ Messages.calendar_tempCalendar = "Temp calendar";
|
|||
var edit;
|
||||
if (data.loading) {
|
||||
edit = h('i.fa.fa-spinner.fa-spin');
|
||||
} else if (!data.readOnly) {
|
||||
} else {
|
||||
edit = makeEditDropdown(id, teamId);
|
||||
}
|
||||
var md = Util.find(data, ['content', 'metadata']);
|
||||
|
@ -410,6 +450,7 @@ Messages.calendar_tempCalendar = "Temp calendar";
|
|||
style: 'background-color: '+md.color+';'
|
||||
}),
|
||||
h('span.cp-calendar-title', md.title),
|
||||
isReadOnly(id, teamId) ? h('i.fa.fa-eye', {title: Messages.readonly}) : undefined,
|
||||
edit
|
||||
]);
|
||||
$(calendar).click(function () {
|
||||
|
|
|
@ -96,6 +96,7 @@ ctx.calendars[channel] = {
|
|||
var sendUpdate = function (ctx, c) {
|
||||
ctx.emit('UPDATE', {
|
||||
teams: c.stores,
|
||||
roTeams: c.roStores,
|
||||
id: c.channel,
|
||||
loading: !c.ready && !c.cacheready,
|
||||
readOnly: c.readOnly || (!c.ready && c.cacheready),
|
||||
|
@ -135,12 +136,38 @@ ctx.calendars[channel] = {
|
|||
|
||||
if (c) {
|
||||
if (c.readOnly && data.href) {
|
||||
// XXX UPGRADE
|
||||
// c.hashes.editHash =
|
||||
// XXX different cases if already ready or not?
|
||||
// Upgrade readOnly calendar to editable
|
||||
var upgradeParsed = Hash.parsePadUrl(data.href);
|
||||
var upgradeSecret = Hash.getSecrets('calendar', upgradeParsed.hash, data.password);
|
||||
var upgradeCrypto = Crypto.createEncryptor(upgradeSecret.keys);
|
||||
c.hashes.editHash = Hash.getEditHashFromKeys(upgradeSecret);
|
||||
c.lm.setReadOnly(false, upgradeCrypto);
|
||||
c.readOnly = false;
|
||||
} else if (teamId === 0) {
|
||||
// Existing calendars can't be "temp calendars" (unless they are an upgrade)
|
||||
return void cb();
|
||||
}
|
||||
|
||||
// Remove from roStores when upgrading this store
|
||||
if (c.roStores.indexOf(teamId) !== -1 && data.href) {
|
||||
c.roStores.splice(c.roStores.indexOf(teamId), 1);
|
||||
// If we've upgraded a stored calendar, remove the temp calendar
|
||||
if (c.stores.indexOf(0) !== -1) {
|
||||
c.stores.splice(c.stores.indexOf(0), 1);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
// Don't store duplicates
|
||||
if (c.stores && c.stores.indexOf(teamId) !== -1) { return void cb(); }
|
||||
|
||||
// If we store a temp calendar to our account or team, remove this "temp calendar"
|
||||
if (c.stores.indexOf(0) !== -1) { c.stores.splice(c.stores.indexOf(0), 1); }
|
||||
|
||||
c.stores.push(teamId);
|
||||
if (!data.href) {
|
||||
c.roStores.push(teamId);
|
||||
}
|
||||
update();
|
||||
return void cb();
|
||||
}
|
||||
|
@ -152,6 +179,7 @@ ctx.calendars[channel] = {
|
|||
channel: channel,
|
||||
readOnly: !data.href,
|
||||
stores: [teamId],
|
||||
roStores: data.href ? [] : [teamId],
|
||||
hashes: {}
|
||||
};
|
||||
|
||||
|
@ -343,6 +371,38 @@ ctx.calendars[channel] = {
|
|||
isNew: true
|
||||
}, cb);
|
||||
};
|
||||
var importCalendar = function (ctx, data, cId, cb) {
|
||||
var id = data.id;
|
||||
var c = ctx.calendars[id];
|
||||
if (!c) { return void cb({error: "ENOENT"}); }
|
||||
if (!Array.isArray(c.stores) || c.stores.indexOf(data.teamId) === -1) {
|
||||
return void cb({error: 'EINVAL'});
|
||||
}
|
||||
|
||||
// Add to my calendars
|
||||
var store = ctx.store;
|
||||
var calendars = store.proxy.calendars = store.proxy.calendars || {};
|
||||
var hash = c.hashes.editHash;
|
||||
var roHash = c.hashes.viewHash;
|
||||
calendars[id] = {
|
||||
href: hash && Hash.hashToHref(hash, 'calendar'),
|
||||
roHref: roHash && Hash.hashToHref(roHash, 'calendar'),
|
||||
channel: id,
|
||||
color: Util.find(c,['proxy', 'metadata', 'color']) || Util.getRandomColor(),
|
||||
title: Util.find(c,['proxy', 'metadata', 'title']) || '...'
|
||||
};
|
||||
ctx.Store.onSync(null, cb);
|
||||
|
||||
// Make the change in memory
|
||||
openChannel(ctx, {
|
||||
storeId: 1,
|
||||
data: {
|
||||
href: calendars[id].href,
|
||||
toHref: calendars[id].roHref,
|
||||
channel: id
|
||||
}
|
||||
});
|
||||
};
|
||||
var addCalendar = function (ctx, data, cId, cb) {
|
||||
var store = getStore(ctx, data.teamId);
|
||||
if (!store) { return void cb({error: "NO_STORE"}); }
|
||||
|
@ -353,13 +413,21 @@ ctx.calendars[channel] = {
|
|||
var parsed = Hash.parsePadUrl(data.href);
|
||||
var secret = Hash.getSecrets(parsed.type, parsed.hash, data.password);
|
||||
|
||||
if (secret.channel !== data.channel) { return void cb({error: 'EINVAL'}); }
|
||||
|
||||
var hash = Hash.getEditHashFromKeys(secret);
|
||||
var roHash = Hash.getViewHashFromKeys(secret);
|
||||
var cal = {
|
||||
href: Hash.getEditHashFromKeys(secret),
|
||||
roHref: Hash.getViewHashFromKeys(secret),
|
||||
href: hash && Hash.hashToHref(hash, 'calendar'),
|
||||
roHref: roHash && Hash.hashToHref(roHash, 'calendar'),
|
||||
color: data.color,
|
||||
title: data.title,
|
||||
channel: data.channel
|
||||
};
|
||||
|
||||
// If it already existed and it's not an upgrade, nothing to do
|
||||
if (c[data.channel] && (c[data.channel].href || !cal.href)) { return void cb(); }
|
||||
|
||||
cal.color = data.color;
|
||||
cal.title = data.title;
|
||||
openChannel(ctx, {
|
||||
|
@ -373,6 +441,7 @@ ctx.calendars[channel] = {
|
|||
return void cb({error: err.error})
|
||||
}
|
||||
// Add the calendar and call back
|
||||
// If it already existed it means this is an upgrade
|
||||
c[cal.channel] = cal;
|
||||
var pin = store.pin || ctx.pinPads;
|
||||
pin([cal.channel], function (res) {
|
||||
|
@ -539,6 +608,10 @@ ctx.calendars[channel] = {
|
|||
});
|
||||
return;
|
||||
}
|
||||
if (cmd === 'IMPORT') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
return void importCalendar(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'ADD') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
return void addCalendar(ctx, data, clientId, cb);
|
||||
|
|
Loading…
Reference in New Issue