encryption updates

This commit is contained in:
Mo Bitar
2016-12-12 20:00:21 -06:00
parent 8ad3776819
commit d200df0b85
12 changed files with 136 additions and 144 deletions

View File

@@ -235,11 +235,13 @@ angular.module('app.frontend')
this.saveUrl = function($event) {
$event.target.blur();
var original = this.note.presentation.root_path;
this.note.presentation.root_path = this.url.token;
apiController.saveNote(this.user, this.note, function(note){
if(!note) {
this.note.token = original;
var original = this.note.presentation.relative_path;
this.note.presentation.relative_path = this.url.token;
apiController.updatePresentation(this.note, this.note.presentation, function(response){
if(!response) {
this.note.presentation.relative_path = original;
this.url.token = original;
alert("This URL is not available.");
} else {

View File

@@ -53,7 +53,7 @@ angular.module('app.frontend')
return;
}
this.newGroup = {notes : []};
this.newGroup = new Group({notes : []});
if(!this.user.id) {
this.newGroup.id = Neeto.crypto.generateRandomKey()
}
@@ -92,7 +92,7 @@ angular.module('app.frontend')
}
this.noteCount = function(group) {
var validNotes = apiController.filterDummyNotes(group.notes);
var validNotes = Note.filterDummyNotes(group.notes);
return validNotes.length;
}

View File

@@ -13,17 +13,7 @@ angular.module('app.frontend')
bindToController: true,
link:function(scope, elem, attrs, ctrl) {
// scope.$on('auth:login-success', function(event, user) {
// ctrl.onAuthSuccess(user);
// });
scope.$on('auth:validation-success', function(ev) {
// TODO
setTimeout(function(){
ctrl.onValidationSuccess();
})
});
}
}
})
@@ -118,17 +108,11 @@ angular.module('app.frontend')
}.bind(this));
}
this.onValidationSuccess = function() {
apiController.verifyEncryptionStatusOfAllNotes(this.user, function(success){
});
}
this.encryptionStatusForNotes = function() {
var allNotes = this.user.filteredNotes();
var countEncrypted = 0;
allNotes.forEach(function(note){
if(note.isEncrypted()) {
if(note.encryptionEnabled()) {
countEncrypted++;
}
}.bind(this))

View File

@@ -6,21 +6,12 @@ angular.module('app.frontend')
var onUserSet = function() {
$scope.defaultUser.notes = _.map($scope.defaultUser.notes, function(json_obj) {
return new Note(json_obj);
});
$scope.allGroup = new Group({name: "All", all: true});
$scope.groups = $scope.defaultUser.groups;
$scope.defaultUser.filteredNotes = function() {
return apiController.filterDummyNotes($scope.defaultUser.notes);
}
var groups = $scope.defaultUser.groups;
var allNotes = $scope.defaultUser.notes;
groups.forEach(function(group){
var notes = allNotes.filter(function(note){return note.group_id && note.group_id == group.id});
group.notes = notes;
})
$scope.allGroup = {name: "All", all: true};
$scope.groups = groups;
apiController.verifyEncryptionStatusOfAllNotes($scope.defaultUser, function(success){
});
}
apiController.getCurrentUser(function(response){
@@ -39,7 +30,7 @@ angular.module('app.frontend')
*/
$scope.updateAllGroup = function() {
var allNotes = apiController.filterDummyNotes($scope.defaultUser.notes);
var allNotes = Note.filterDummyNotes($scope.defaultUser.notes);
$scope.defaultUser.notes = allNotes;
$scope.allGroup.notes = allNotes;
}
@@ -78,6 +69,8 @@ angular.module('app.frontend')
originalNote.group_id = null;
} else {
originalNote.group_id = newGroup.id
originalNote.group = newGroup;
newGroup.notes.unshift(originalNote);
newGroup.notes.sort(function(a,b){
//subtract to get a value that is either negative, positive, or zero.
@@ -85,8 +78,6 @@ angular.module('app.frontend')
});
}
originalNote.shared_via_group = newGroup.presentation && newGroup.presentation.enabled;
apiController.saveNote($scope.defaultUser, originalNote, function(note){
_.merge(originalNote, note);
});
@@ -97,7 +88,7 @@ angular.module('app.frontend')
*/
$scope.notesRemoveGroup = function(group) {
var validNotes = apiController.filterDummyNotes(group.notes);
var validNotes = Note.filterDummyNotes(group.notes);
if(validNotes == 0) {
// if no more notes, delete group
apiController.deleteGroup($scope.defaultUser, group, function(){

View File

@@ -138,7 +138,7 @@ angular.module('app.frontend')
var title = "New Note" + (this.notes ? (" " + (this.notes.length + 1)) : "");
this.newNote = new Note({dummy: true});
this.newNote.content.title = title;
this.newNote.shared_via_group = this.group.presentation && this.group.presentation.enabled;
this.newNote.group = this.group;
this.selectNote(this.newNote);
this.addNew()(this.newNote);
}

View File

@@ -0,0 +1,3 @@
var Group = function (json_obj) {
_.merge(this, json_obj);
};

View File

@@ -23,6 +23,10 @@ var Note = function (json_obj) {
enumerable: true,
});
this.setContentRaw = function(rawContent) {
content = rawContent;
}
_.merge(this, json_obj);
if(!this.content) {
@@ -30,17 +34,22 @@ var Note = function (json_obj) {
}
};
Note.filterDummyNotes = function(notes) {
var filtered = notes.filter(function(note){return note.dummy == false || note.dummy == null});
return filtered;
}
/* Returns true if note is shared individually or via group */
Note.prototype.isPublic = function() {
return this.hasEnabledPresentation() || this.shared_via_group;
return this.presentation || (this.group && this.group.presentation);
};
Note.prototype.isEncrypted = function() {
return (this.loc_eek || this.local_eek) && typeof this.content === 'string' ? true : false;
return this.encryptionEnabled() && typeof this.content === 'string' ? true : false;
}
Note.prototype.hasEnabledPresentation = function() {
return this.presentation && this.presentation.enabled;
Note.prototype.encryptionEnabled = function() {
return this.loc_eek;
}
Note.prototype.presentationURL = function() {

View File

@@ -1,3 +1,23 @@
var User = function (json_obj) {
_.merge(this, json_obj);
this.notes = _.map(this.notes, function(json_obj) {
return new Note(json_obj);
});
this.groups = _.map(this.groups, function(json_obj) {
return new Group(json_obj);
});
this.groups.forEach(function(group){
var notes = this.notes.filter(function(note){return note.group_id && note.group_id == group.id});
notes.forEach(function(note){
note.group = group;
})
group.notes = notes;
}.bind(this))
};
User.prototype.filteredNotes = function() {
return Note.filterDummyNotes(this.notes);
}

View File

@@ -147,25 +147,21 @@ angular.module('app.services')
this.verifyEncryptionStatusOfAllNotes = function(user, callback) {
var allNotes = user.filteredNotes();
var notesNeedingUpdate = [];
var key = this.retrieveGk();
allNotes.forEach(function(note){
if(!note.isPublic()) {
if(!note.isEncrypted()) {
// needs encryption
this.encryptSingleNote(note, key);
if(note.encryptionEnabled() && !note.isEncrypted()) {
notesNeedingUpdate.push(note);
}
} else {
if(note.isEncrypted()) {
// needs decrypting
this.decryptSingleNote(note, key);
notesNeedingUpdate.push(note);
}
}
}.bind(this))
if(notesNeedingUpdate.length > 0) {
this.saveBatchNotes(user, notesNeedingUpdate, true, callback)
console.log("verifying encryption, notes need updating", notesNeedingUpdate);
this.saveBatchNotes(user, notesNeedingUpdate, callback)
}
}
@@ -210,41 +206,31 @@ angular.module('app.services')
}
this.shareGroup = function(user, group, callback) {
var shareFn = function() {
Restangular.one("users", user.id).one("groups", group.id).one("presentations").post()
.then(function(response){
var presentation = response.plain();
group.notes.forEach(function(note){
note.shared_via_group = true;
});
_.merge(group, {presentation: presentation});
callback(presentation);
})
}
if(group.notes.length > 0) {
// decrypt group notes first
var notes = group.notes;
notes.forEach(function(note){
note.shared_via_group = true;
})
this.decryptNotesWithLocalKey(notes);
this.saveBatchNotes(user, notes, false, function(success){
shareFn();
})
} else {
shareFn();
}
if(group.notes.length > 0) {
// decrypt notes
this.saveBatchNotes(user, group.notes, function(success){})
}
}.bind(this))
}
this.unshareGroup = function(user, group, callback) {
var request = Restangular.one("users", user.id).one("groups", group.id).one("presentations", group.presentation.id);
request.enabled = false;
request.patch().then(function(response){
var presentation = response.plain();
_.merge(group, {presentation: presentation});
callback(presentation);
})
request.remove().then(function(response){
group.presentation = null;
callback(null);
if(group.notes.length > 0) {
// encrypt notes
var notes = group.notes;
this.saveBatchNotes(user, notes, function(success){})
}
}.bind(this))
}
@@ -255,7 +241,7 @@ angular.module('app.services')
Notes
*/
this.saveBatchNotes = function(user, notes, encryptionEnabled, callback) {
this.saveBatchNotes = function(user, notes, callback) {
var request = Restangular.one("users", user.id).one("notes/batch_update");
request.notes = _.map(notes, function(note){
return this.createRequestParamsFromNote(note, user);
@@ -302,6 +288,7 @@ angular.module('app.services')
else {
// decrypted
params.content = JSON.stringify(note.content);
params.loc_eek = null;
}
return params;
}
@@ -351,15 +338,29 @@ angular.module('app.services')
this.unshareNote = function(user, note, callback) {
var request = Restangular.one("users", user.id).one("notes", note.id).one("presentations", note.presentation.id);
request.enabled = false;
request.patch().then(function(response){
var presentation = response.plain();
_.merge(note, {presentation: presentation});
callback(note);
request.remove().then(function(response){
note.presentation = null;
callback(null);
})
}
/*
Presentations
*/
this.updatePresentation = function(resource, presentation, callback) {
var request = Restangular.one("users", user.id)
.one(resource.constructor.name.toLowerCase() + "s", resource.id)
.one("presentations", resource.presentation.id);
_.merge(request, presentation);
request.patch().then(function(response){
callback(response.plain());
})
.catch(function(error){
callback(nil);
})
}
/*
@@ -368,32 +369,26 @@ angular.module('app.services')
this.importJSONData = function(jsonString, callback) {
var data = JSON.parse(jsonString);
var user = new User(data);
console.log("importing data", JSON.parse(jsonString));
// data.notes = _.map(data.notes, function(json_obj) {
// return new Note(json_obj);
// });
console.log("objectifying data", this.staticifyObject(data));
data.notes.forEach(function(note){
var presentation = data.presentations.find(function(presentation){
return presentation.presentable_type == "Note" && presentation.presentable_id == note.id;
})
if(presentation) {
// public
// console.log("public note", note);
note.content = JSON.stringify(note.content);
// console.log("after json", note);
user.notes.forEach(function(note) {
if(note.isPublic()) {
note.setContentRaw(JSON.stringify(note.content));
} else {
// private
this.encryptSingleNoteWithLocalKey(note);
}
// prevent circular links
note.group = null;
}.bind(this))
user.groups.forEach(function(group){
// prevent circular links
group.notes = null;
})
var request = Restangular.one("import");
request.data = data;
console.log("posting import request", request);
request.data = {notes: user.notes, groups: user.groups};
request.post().then(function(response){
callback(true, response);
})
@@ -423,9 +418,24 @@ angular.module('app.services')
return textFile;
}.bind(this);
var presentationParams = function(presentation) {
if(!presentation) {
return null;
}
return {
id: presentation.id,
uuid: presentation.uuid,
root_path: presentation.root_path,
relative_path: presentation.relative_path,
presentable_type: presentation.presentable_type,
presentable_id: presentation.presentable_id,
created_at: presentation.created_at,
modified_at: presentation.modified_at,
}
}
var notes = _.map(user.filteredNotes(), function(note){
console.log("mapping note", note);
return {
id: note.id,
uuid: note.uuid,
@@ -433,6 +443,7 @@ angular.module('app.services')
group_id: note.group_id,
created_at: note.created_at,
modified_at: note.modified_at,
presentation: presentationParams(note.presentation)
}
});
@@ -443,36 +454,13 @@ angular.module('app.services')
name: group.name,
created_at: group.created_at,
modified_at: group.modified_at,
}
});
var modelsWithPresentations = user.groups.concat(user.notes).filter(function(model){
return model.presentation != null;
})
var presentations = _.map(modelsWithPresentations, function(model){
return model.presentation;
})
presentations = _.map(presentations, function(presentation){
return {
id: presentation.id,
uuid: presentation.uuid,
host: presentation.host,
root_path: presentation.root_path,
relative_path: presentation.relative_path,
presentable_type: presentation.presentable_type,
presentable_id: presentation.presentable_id,
enabled: presentation.enabled,
created_at: presentation.created_at,
modified_at: presentation.modified_at,
presentation: presentationParams(group.presentation)
}
});
var data = {
notes: notes,
groups: groups,
presentations: presentations
groups: groups
}
return makeTextFile(JSON.stringify(data, null, 2 /* pretty print */));
@@ -505,18 +493,13 @@ angular.module('app.services')
this.filterDummyNotes = function(notes) {
var filtered = notes.filter(function(note){return note.dummy == false || note.dummy == null});
return filtered;
}
this.staticifyObject = function(object) {
return JSON.parse(JSON.stringify(object));
}
this.writeUserToLocalStorage = function(user) {
var saveUser = _.cloneDeep(user);
saveUser.notes = this.filterDummyNotes(saveUser.notes);
saveUser.notes = Note.filterDummyNotes(saveUser.notes);
saveUser.groups.forEach(function(group){
group.notes = null;
}.bind(this))
@@ -645,7 +628,7 @@ angular.module('app.services')
}
});
this.saveBatchNotes(user, notes, true, function(success) {
this.saveBatchNotes(user, notes, function(success) {
callback(success);
}.bind(this));
}

View File

@@ -26,11 +26,11 @@
%li
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.toggleMarkdown()"} Toggle Markdown Preview
.shortcut Cmd + M
%li{"ng-if" => "!ctrl.note.hasEnabledPresentation()"}
%li{"ng-if" => "!ctrl.note.presentation"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.shareNote()"} Share
%li{"ng-if" => "ctrl.note.hasEnabledPresentation()"}
%li{"ng-if" => "ctrl.note.presentation"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.editUrlPressed()"} Edit URL
%li{"ng-if" => "ctrl.note.hasEnabledPresentation()"}
%li{"ng-if" => "ctrl.note.presentation"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.unshareNote()"} Unshare
%li
%a.text{"ng-click" => "ctrl.deleteNote()"} Delete
@@ -40,7 +40,7 @@
.panel-body{"style" => "text-align: center; color: black;"}
This editor is Markdown enabled.
.menu-right-container
.public-link{"ng-if" => "ctrl.note.hasEnabledPresentation()"}
.public-link{"ng-if" => "ctrl.note.presentation"}
%a.url{"ng-if" => "!ctrl.editingUrl", "href" => "{{ctrl.publicUrlForNote(ctrl.note)}}", "target" => "_blank"}
%span.icon-rss.icon
{{ctrl.publicUrlForNote(note)}}

View File

@@ -9,7 +9,7 @@
.count {{ctrl.noteCount(ctrl.allGroup)}}
.group{"ng-repeat" => "group in ctrl.groups", "ng-click" => "ctrl.selectGroup(group)", "ng-class" => "{'selected' : ctrl.selectedGroup == group}",
"droppable" => true, "drop" => "ctrl.handleDrop", "group" => "group"}
.icon.icon-rss{"ng-if" => "group.presentation.enabled"}
.icon.icon-rss{"ng-if" => "group.presentation"}
%input.title{"ng-disabled" => "group != ctrl.selectedGroup", "ng-model" => "group.name",
"ng-keyup" => "$event.keyCode == 13 && ctrl.saveGroup($event, group)", "mb-autofocus" => "true", "should-focus" => "ctrl.newGroup",
"ng-change" => "ctrl.groupTitleDidChange(group)", "ng-focus" => "ctrl.onGroupTitleFocus(group)"}

View File

@@ -14,14 +14,14 @@
%span.caret
%span.sr-only
%ul.dropdown-menu.dropdown-menu-left.nt-dropdown-menu.dark{"ng-if" => "ctrl.showMenu"}
%li{"ng-if" => "!ctrl.group.presentation.enabled"}
%li{"ng-if" => "!ctrl.group.presentation"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedGroupShare($event)"} Share Group
%li{"ng-if" => "ctrl.group.presentation.enabled"}
%li{"ng-if" => "ctrl.group.presentation"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedGroupUnshare()"} Unshare Group
%li{"ng-if" => "!ctrl.group.all"}
%a.text{"ng-click" => "ctrl.selectedMenuItem(); ctrl.selectedGroupDelete()"} Delete Group
.menu-right-container
.public-link{"ng-if" => "ctrl.group.presentation.enabled"}
.public-link{"ng-if" => "ctrl.group.presentation"}
%a.url{"ng-if" => "!ctrl.editingUrl", "href" => "{{ctrl.publicUrlForGroup(ctrl.group)}}", "target" => "_blank"}
%span.icon-rss.icon
{{ctrl.publicUrlForGroup()}}