Move etsync decryption logic to sync gate.

This shares more of the code, and also lets us be more efficient because
we now do these calculations less.
master
Tom Hacohen 2017-12-14 14:31:17 +00:00
parent 6c4f077d0f
commit 9f396173b0
3 changed files with 89 additions and 84 deletions

View File

@ -1,8 +1,6 @@
import * as React from 'react';
import { Tabs, Tab } from 'material-ui/Tabs';
import * as EteSync from './api/EteSync';
import Container from './Container';
import SecondaryHeader from './SecondaryHeader';
@ -10,16 +8,13 @@ import SecondaryHeader from './SecondaryHeader';
import JournalEntries from './JournalEntries';
import JournalAddressBook from './JournalAddressBook';
import JournalCalendar from './JournalCalendar';
import LoadingIndicator from './LoadingIndicator';
import { syncEntriesToItemMap, syncEntriesToCalendarItemMap } from './journal-processors';
import { JournalsData, EntriesType, CredentialsData } from './store';
import { SyncInfo } from './SyncGate';
interface PropsType {
journals: JournalsData;
entries: EntriesType;
etesync: CredentialsData;
syncInfo: SyncInfo;
match: any;
}
@ -39,29 +34,15 @@ class Journal extends React.PureComponent {
render() {
const journalUid = this.props.match.params.journalUid;
const entries = this.props.entries.get(journalUid);
if ((!entries) || (entries.value === null)) {
return (<LoadingIndicator />);
}
const journal = this.props.journals.find((x) => (x.uid === journalUid));
if (journal === undefined) {
const syncJournal = this.props.syncInfo.get(journalUid);
if (!syncJournal) {
return (<div>Journal not found!</div>);
}
const derived = this.props.etesync.encryptionKey;
let prevUid: string | null = null;
const cryptoManager = new EteSync.CryptoManager(derived, journal.uid, journal.version);
const collectionInfo = journal.getInfo(cryptoManager);
const syncEntries = entries.value.map((entry) => {
let syncEntry = entry.getSyncEntry(cryptoManager, prevUid);
prevUid = entry.uid;
return syncEntry;
});
const journal = syncJournal.journal;
const collectionInfo = syncJournal.collection;
const syncEntries = syncJournal.entries;
let itemsTitle: string;
let itemsView: JSX.Element;

View File

@ -17,7 +17,9 @@ import PimMain from './PimMain';
import { routeResolver } from './App';
import { store, JournalsData, EntriesType, CredentialsData } from './store';
import { store, CredentialsData } from './store';
import { SyncInfo } from './SyncGate';
import { createJournalEntry } from './etesync-helpers';
@ -30,8 +32,7 @@ function objValues(obj: any) {
class Pim extends React.PureComponent {
props: {
etesync: CredentialsData;
journals: JournalsData;
entries: EntriesType;
syncInfo: SyncInfo;
match: any;
history: any;
};
@ -43,97 +44,68 @@ class Pim extends React.PureComponent {
}
onEventSave(event: EventType, journalUid: string, originalEvent?: EventType) {
const journal = this.props.journals.find((x) => (x.uid === journalUid));
const syncJournal = this.props.syncInfo.get(journalUid);
if (journal === undefined) {
if (syncJournal === undefined) {
return;
}
const entries = this.props.entries.get(journal.uid);
if (!entries) {
return;
}
if (entries.value === null) {
return;
}
const journal = syncJournal.journal;
let action = (originalEvent === undefined) ? EteSync.SyncEntryAction.Add : EteSync.SyncEntryAction.Change;
let saveEvent = store.dispatch(
createJournalEntry(this.props.etesync, journal, entries.value, action, event.toIcal()));
createJournalEntry(this.props.etesync, journal, syncJournal.journalEntries, action, event.toIcal()));
(saveEvent as any).then(() => {
this.props.history.goBack();
});
}
onContactSave(contact: ContactType, journalUid: string, originalContact?: ContactType) {
const journal = this.props.journals.find((x) => (x.uid === journalUid));
const syncJournal = this.props.syncInfo.get(journalUid);
if (journal === undefined) {
if (syncJournal === undefined) {
return;
}
const entries = this.props.entries[journal.uid];
if (entries.value === null) {
return;
}
const journal = syncJournal.journal;
let action = (originalContact === undefined) ? EteSync.SyncEntryAction.Add : EteSync.SyncEntryAction.Change;
let saveContact = store.dispatch(
createJournalEntry(this.props.etesync, journal, entries.value, action, contact.toIcal()));
createJournalEntry(this.props.etesync, journal, syncJournal.journalEntries, action, contact.toIcal()));
(saveContact as any).then(() => {
this.props.history.goBack();
});
}
render() {
const derived = this.props.etesync.encryptionKey;
let collectionsAddressBook: Array<EteSync.CollectionInfo> = [];
let collectionsCalendar: Array<EteSync.CollectionInfo> = [];
const journalMap = this.props.journals.reduce(
(ret, journal) => {
const journalEntries = this.props.entries.get(journal.uid);
const cryptoManager = new EteSync.CryptoManager(derived, journal.uid, journal.version);
let prevUid: string | null = null;
if (!journalEntries || !journalEntries.value) {
return ret;
}
let entriesAddressBook: Array<{[key: string]: ContactType}> = [];
let entriesCalendar: Array<{[key: string]: EventType}> = [];
this.props.syncInfo.forEach(
(syncJournal) => {
const syncEntries = syncJournal.entries;
const journal = syncJournal.journal;
// FIXME: Skip shared journals for now
if (journal.key) {
return ret;
return;
}
const collectionInfo = journal.getInfo(cryptoManager);
const syncEntries = journalEntries.value.map((entry: EteSync.Entry) => {
let syncEntry = entry.getSyncEntry(cryptoManager, prevUid);
prevUid = entry.uid;
return syncEntry;
});
const collectionInfo = syncJournal.collection;
if (collectionInfo.type === 'ADDRESS_BOOK') {
ret.ADDRESS_BOOK.push(syncEntriesToItemMap(collectionInfo, syncEntries));
entriesAddressBook.push(syncEntriesToItemMap(collectionInfo, syncEntries));
collectionsAddressBook.push(collectionInfo);
} else if (collectionInfo.type === 'CALENDAR') {
ret.CALENDAR.push(syncEntriesToCalendarItemMap(collectionInfo, syncEntries));
entriesCalendar.push(syncEntriesToCalendarItemMap(collectionInfo, syncEntries));
collectionsCalendar.push(collectionInfo);
}
}
);
return ret;
},
{ CALENDAR: [] as Array<{[key: string]: EventType}>,
ADDRESS_BOOK: [] as Array<{[key: string]: ContactType}>,
UNSUPPORTED: [] as Array<any>});
let addressBookItems = journalMap.ADDRESS_BOOK.reduce((base, x) => Object.assign(base, x), {});
let calendarItems = journalMap.CALENDAR.reduce((base, x) => Object.assign(base, x), {});
let addressBookItems = entriesAddressBook.reduce((base, x) => Object.assign(base, x), {});
let calendarItems = entriesCalendar.reduce((base, x) => Object.assign(base, x), {});
return (
<Switch>

View File

@ -2,6 +2,8 @@ import * as React from 'react';
import { connect } from 'react-redux';
import { Route, Switch, Redirect, withRouter } from 'react-router';
import { List, Map } from 'immutable';
import { routeResolver } from './App';
import LoadingIndicator from './LoadingIndicator';
@ -9,8 +11,19 @@ import LoadingIndicator from './LoadingIndicator';
import Journal from './Journal';
import Pim from './Pim';
import * as EteSync from './api/EteSync';
import { store, JournalsType, EntriesType, fetchJournals, fetchEntries, StoreState, CredentialsData } from './store';
export interface SyncInfoJournal {
journal: EteSync.Journal;
journalEntries: List<EteSync.Entry>;
collection: EteSync.CollectionInfo;
entries: List<EteSync.SyncEntry>;
}
export type SyncInfo = Map<string, SyncInfoJournal>;
interface PropsType {
etesync: CredentialsData;
}
@ -55,6 +68,43 @@ class SyncGate extends React.PureComponent {
return (<LoadingIndicator />);
}
const derived = this.props.etesync.encryptionKey;
const journalMap = journals.reduce(
(ret, journal) => {
const journalEntries = this.props.entries.get(journal.uid);
const cryptoManager = new EteSync.CryptoManager(derived, journal.uid, journal.version);
let prevUid: string | null = null;
if (!journalEntries || !journalEntries.value) {
return ret;
}
// FIXME: Skip shared journals for now
if (journal.key) {
return ret;
}
const collectionInfo = journal.getInfo(cryptoManager);
const syncEntries = journalEntries.value.map((entry: EteSync.Entry) => {
let syncEntry = entry.getSyncEntry(cryptoManager, prevUid);
prevUid = entry.uid;
return syncEntry;
});
return ret.set(journal.uid, {
entries: syncEntries,
collection: collectionInfo,
journal,
journalEntries: journalEntries.value,
});
},
Map<string, SyncInfoJournal>()
);
return (
<Switch>
<Route
@ -69,8 +119,7 @@ class SyncGate extends React.PureComponent {
render={({match, history}) => (
<Pim
etesync={this.props.etesync}
journals={journals}
entries={this.props.entries}
syncInfo={journalMap}
match={match}
history={history}
/>
@ -79,8 +128,11 @@ class SyncGate extends React.PureComponent {
<Route
path={routeResolver.getRoute('journals._id')}
render={({match}) => (
<Journal etesync={this.props.etesync} journals={journals} entries={this.props.entries} match={match} />
)}
<Journal
syncInfo={journalMap}
match={match}
/>
)}
/>
</Switch>
);