From 7bbd18e75c90c35d92e16e1ae22e04d7dea0e0a8 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Sat, 10 Dec 2016 21:32:29 -0600 Subject: [PATCH] spec compliance wip --- app/assets/javascripts/app/app.services.js | 14 ++ .../app/frontend/controllers/editor.js | 34 +-- .../app/frontend/controllers/header.js | 93 +++----- .../app/frontend/controllers/home.js | 12 +- .../app/frontend/controllers/notes.js | 6 +- .../javascripts/app/frontend/models/note.js | 19 +- .../javascripts/app/services/apiController.js | 208 ++++++++++++------ .../app/services/directives/snippet.js | 2 +- .../templates/frontend/editor.html.haml | 4 +- app/assets/templates/frontend/notes.html.haml | 2 +- .../initializers/filter_parameter_logging.rb | 2 +- 11 files changed, 231 insertions(+), 165 deletions(-) diff --git a/app/assets/javascripts/app/app.services.js b/app/assets/javascripts/app/app.services.js index 4b8ef67a4..3bb263cb5 100644 --- a/app/assets/javascripts/app/app.services.js +++ b/app/assets/javascripts/app/app.services.js @@ -9,6 +9,20 @@ angular .config(function (RestangularProvider, apiControllerProvider) { var url = apiControllerProvider.defaultServerURL(); RestangularProvider.setBaseUrl(url); + + RestangularProvider.setFullRequestInterceptor(function(element, operation, route, url, headers, params, httpConfig) { + var token = localStorage.getItem("jwt"); + if(token) { + headers = _.extend(headers, {Authorization: "Bearer " + localStorage.getItem("jwt")}); + } + + return { + element: element, + params: params, + headers: headers, + httpConfig: httpConfig + }; + }); }) // Shared function for configure auth service. Can be overwritten. diff --git a/app/assets/javascripts/app/frontend/controllers/editor.js b/app/assets/javascripts/app/frontend/controllers/editor.js index ce9da5f09..b96f7915a 100644 --- a/app/assets/javascripts/app/frontend/controllers/editor.js +++ b/app/assets/javascripts/app/frontend/controllers/editor.js @@ -66,25 +66,25 @@ angular.module('app.frontend') .controller('EditorCtrl', function ($sce, $timeout, apiController, markdownRenderer, $rootScope) { this.demoNotes = [ - {name: "Live print a file with tail", content: "tail -f log/production.log"}, - {name: "Create SSH tunnel", content: "ssh -i .ssh/key.pem -N -L 3306:example.com:3306 ec2-user@example.com"}, - {name: "List of processes running on port", content: "lsof -i:8080"}, - {name: "Set ENV from file", content: "export $(cat .envfile | xargs)"}, - {name: "Find process by name", content: "ps -ax | grep "}, - {name: "NPM install without sudo", content: "sudo chown -R $(whoami) ~/.npm"}, - {name: "Email validation regex", content: "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"}, - {name: "Ruby generate 256 bit key", content: "Digest::SHA256.hexdigest(SecureRandom.random_bytes(32))"}, - {name: "Mac add user to user group", content: "sudo dseditgroup -o edit -a USERNAME -t user GROUPNAME"}, - {name: "Kill Mac OS System Apache", content: "sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist"}, - {name: "Docker run with mount binding and port", content: "docker run -v /home/vagrant/www/app:/var/www/app -p 8080:80 -d kpi/s3"}, - {name: "MySQL grant privileges", content: "GRANT [type of permission] ON [database name].[table name] TO ‘[username]’@'%’;"}, - {name: "MySQL list users", content: "SELECT User FROM mysql.user;"}, + {title: "Live print a file with tail", content: "tail -f log/production.log"}, + {title: "Create SSH tunnel", content: "ssh -i .ssh/key.pem -N -L 3306:example.com:3306 ec2-user@example.com"}, + {title: "List of processes running on port", content: "lsof -i:8080"}, + {title: "Set ENV from file", content: "export $(cat .envfile | xargs)"}, + {title: "Find process by name", content: "ps -ax | grep "}, + {title: "NPM install without sudo", content: "sudo chown -R $(whoami) ~/.npm"}, + {title: "Email validation regex", content: "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"}, + {title: "Ruby generate 256 bit key", content: "Digest::SHA256.hexdigest(SecureRandom.random_bytes(32))"}, + {title: "Mac add user to user group", content: "sudo dseditgroup -o edit -a USERNAME -t user GROUPNAME"}, + {title: "Kill Mac OS System Apache", content: "sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist"}, + {title: "Docker run with mount binding and port", content: "docker run -v /home/vagrant/www/app:/var/www/app -p 8080:80 -d kpi/s3"}, + {title: "MySQL grant privileges", content: "GRANT [type of permission] ON [database name].[table name] TO ‘[username]’@'%’;"}, + {title: "MySQL list users", content: "SELECT User FROM mysql.user;"}, ]; this.showSampler = !this.user.id && this.user.filteredNotes().length == 0; this.demoNoteNames = _.map(this.demoNotes, function(note){ - return note.name; + return note.title; }); this.currentDemoContent = {text: null}; @@ -94,7 +94,7 @@ angular.module('app.frontend') }.bind(this) this.callback = function(index) { - this.currentDemoContent.text = this.demoNotes[index].content; + this.currentDemoContent.text = this.demoNotes[index].text; }.bind(this) this.contentCallback = function(index) { @@ -102,7 +102,7 @@ angular.module('app.frontend') this.setNote = function(note, oldNote) { this.editorMode = 'edit'; - if(note.content.length == 0) { + if(note.text.length == 0) { this.focusTitle(100); } @@ -138,7 +138,7 @@ angular.module('app.frontend') } this.renderedContent = function() { - return markdownRenderer.renderHtml(markdownRenderer.renderedContentForText(this.note.content)); + return markdownRenderer.renderHtml(markdownRenderer.renderedContentForText(this.note.text)); } var statusTimeout; diff --git a/app/assets/javascripts/app/frontend/controllers/header.js b/app/assets/javascripts/app/frontend/controllers/header.js index 55e46e5ff..4e5bc6271 100644 --- a/app/assets/javascripts/app/frontend/controllers/header.js +++ b/app/assets/javascripts/app/frontend/controllers/header.js @@ -13,9 +13,9 @@ 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:login-success', function(event, user) { + // ctrl.onAuthSuccess(user); + // }); scope.$on('auth:validation-success', function(ev) { setTimeout(function(){ @@ -45,9 +45,8 @@ angular.module('app.frontend') this.signOutPressed = function() { this.showAccountMenu = false; - $auth.signOut(); this.logout()(); - apiController.clearGk(); + apiController.signout(); window.location.reload(); } @@ -55,48 +54,15 @@ angular.module('app.frontend') this.passwordChangeData.status = "Generating New Keys..."; $timeout(function(){ - var current_keys = Neeto.crypto.generateEncryptionKeysForUser(this.passwordChangeData.current_password, this.user.email); - var new_keys = Neeto.crypto.generateEncryptionKeysForUser(this.passwordChangeData.new_password, this.user.email); - // var new_pw_conf_keys = Neeto.crypto.generateEncryptionKeysForUser(this.passwordChangeData.new_password_confirmation, this.user.email); - - var data = {}; - data.current_password = current_keys.pw; - data.password = new_keys.pw; - data.password_confirmation = new_keys.pw; - - var user = this.user; - - if(data.password == data.password_confirmation) { - $auth.updatePassword(data) - .then(function(response) { - this.showNewPasswordForm = false; - if(user.local_encryption_enabled) { - // reencrypt data with new gk - apiController.reencryptAllNotesAndSave(user, new_keys.gk, current_keys.gk, function(success){ - if(success) { - apiController.setGk(new_keys.gk); - alert("Your password has been changed and your data re-encrypted."); - } else { - // rollback password - $auth.updatePassword({current_password: new_keys.pw, password: current_keys.pw, password_confirmation: current_keys.pw }) - .then(function(response){ - alert("There was an error changing your password. Your password has been rolled back."); - window.location.reload(); - }) - } - }); - } else { - alert("Your password has been changed."); - } - }.bind(this)) - .catch(function(response){ - this.showNewPasswordForm = false; - alert("There was an error changing your password. Please try again."); - }.bind(this)) - - } else { + if(data.password != data.password_confirmation) { alert("Your new password does not match its confirmation."); + return; } + + apiController.changePassword(this.user, this.passwordChangeData.current_password, this.passwordChangeData.new_password, function(response){ + + }) + }.bind(this)) } @@ -116,17 +82,14 @@ angular.module('app.frontend') this.loginSubmitPressed = function() { this.loginData.status = "Generating Login Keys..."; $timeout(function(){ - var keys = Neeto.crypto.generateEncryptionKeysForUser(this.loginData.user_password, this.loginData.email); - var data = {password: keys.pw, email: this.loginData.email}; - - apiController.setGk(keys.gk); - $auth.submitLogin(data) - .then(function(response){ - - }) - .catch(function(response){ - this.loginData.status = response.errors[0]; - }.bind(this)) + apiController.login(this.loginData.email, this.loginData.user_password, function(response){ + console.log("login response", response); + if(response.errors) { + this.loginData.status = response.errors[0]; + } else { + this.onAuthSuccess(response.user); + } + }.bind(this)); }.bind(this)) } @@ -134,18 +97,12 @@ angular.module('app.frontend') this.loginData.status = "Generating Account Keys..."; $timeout(function(){ - var keys = Neeto.crypto.generateEncryptionKeysForUser(this.loginData.user_password, this.loginData.email); - var data = {password: keys.pw, email: this.loginData.email}; - - apiController.setGk(keys.gk); - - $auth.submitRegistration(data) - .then(function(response) { - $auth.user.id = response.data.data.id; - this.onAuthSuccess($auth.user); - }.bind(this)) - .catch(function(response) { - this.loginData.status = response.data.errors.full_messages[0]; + apiController.register(this.loginData.email, this.loginData.user_password, function(response){ + if(response.errors) { + this.loginData.status = response.errors[0]; + } else { + this.onAuthSuccess(response.user); + } }.bind(this)); }.bind(this)) } diff --git a/app/assets/javascripts/app/frontend/controllers/home.js b/app/assets/javascripts/app/frontend/controllers/home.js index 0ef95faa2..938f39db5 100644 --- a/app/assets/javascripts/app/frontend/controllers/home.js +++ b/app/assets/javascripts/app/frontend/controllers/home.js @@ -23,16 +23,16 @@ angular.module('app.frontend') $scope.groups = groups; } - $auth.validateUser() - .then(function () { - $scope.defaultUser = new User($auth.user); + apiController.getCurrentUser(function(response){ + console.log("get current response", response); + if(response && !response.errors) { + $scope.defaultUser = new User(response.plain()); $rootScope.title = "Notes — Neeto"; onUserSet(); - - }) - .catch(function () { + } else { $scope.defaultUser = new User(apiController.localUser()); onUserSet(); + } }); /* diff --git a/app/assets/javascripts/app/frontend/controllers/notes.js b/app/assets/javascripts/app/frontend/controllers/notes.js index b695e61eb..354f4c024 100644 --- a/app/assets/javascripts/app/frontend/controllers/notes.js +++ b/app/assets/javascripts/app/frontend/controllers/notes.js @@ -145,8 +145,8 @@ angular.module('app.frontend') } this.createNewNote = function() { - var name = "New Note" + (this.notes ? (" " + (this.notes.length + 1)) : ""); - this.newNote = new Note({name: name, content: '', dummy: true}); + var title = "New Note" + (this.notes ? (" " + (this.notes.length + 1)) : ""); + this.newNote = new Note({title: title, content: '', dummy: true}); this.newNote.shared_via_group = this.group.presentation && this.group.presentation.enabled; this.selectNote(this.newNote); this.addNew()(this.newNote); @@ -158,7 +158,7 @@ angular.module('app.frontend') if(this.noteFilter.text.length == 0) { note.visible = true; } else { - note.visible = note.name.toLowerCase().includes(this.noteFilter.text) || note.content.toLowerCase().includes(this.noteFilter.text); + note.visible = note.title.toLowerCase().includes(this.noteFilter.text) || note.text.toLowerCase().includes(this.noteFilter.text); } return note.visible; }.bind(this) diff --git a/app/assets/javascripts/app/frontend/models/note.js b/app/assets/javascripts/app/frontend/models/note.js index 8df4bf8b3..2b9253ea7 100644 --- a/app/assets/javascripts/app/frontend/models/note.js +++ b/app/assets/javascripts/app/frontend/models/note.js @@ -2,13 +2,30 @@ var Note = function (json_obj) { _.merge(this, json_obj); }; +Note.prototype = { + set content(content) { + try { + var data = JSON.parse(content); + this.title = data.title || data.name; + this.text = data.text || data.content; + } + catch(e) { + this.text = content; + } + } +} + +Note.prototype.JSONContent = function() { + return JSON.stringify({title: this.title, text: this.text}); +}; + /* Returns true if note is shared individually or via group */ Note.prototype.isPublic = function() { return this.hasEnabledPresentation() || this.shared_via_group; }; Note.prototype.isEncrypted = function() { - return this.local_eek ? true : false; + return this.loc_eek || this.local_eek ? true : false; } Note.prototype.hasEnabledPresentation = function() { diff --git a/app/assets/javascripts/app/services/apiController.js b/app/assets/javascripts/app/services/apiController.js index d31bd2a65..571e56c8f 100644 --- a/app/assets/javascripts/app/services/apiController.js +++ b/app/assets/javascripts/app/services/apiController.js @@ -48,6 +48,90 @@ angular.module('app.services') } } + + /* + Auth + */ + + this.getCurrentUser = function(callback) { + if(!localStorage.getItem("jwt")) { + callback(null); + return; + } + Restangular.one("users/current").get().then(function(response){ + callback(response); + }) + } + + this.login = function(email, password, callback) { + var keys = Neeto.crypto.generateEncryptionKeysForUser(password, email); + this.setGk(keys.gk); + var request = Restangular.one("auth/sign_in.json"); + request.user = {password: keys.pw, email: email}; + request.post().then(function(response){ + localStorage.setItem("jwt", response.token); + callback(response); + }) + } + + this.register = function(email, password, callback) { + var keys = Neeto.crypto.generateEncryptionKeysForUser(password, email); + this.setGk(keys.gk); + var request = Restangular.one("auth.json"); + request.user = {password: keys.pw, email: email}; + request.post().then(function(response){ + localStorage.setItem("jwt", response.token); + callback(response); + }) + } + + this.changePassword = function(user, current_password, new_password) { + var current_keys = Neeto.crypto.generateEncryptionKeysForUser(current_password, user.email); + var new_keys = Neeto.crypto.generateEncryptionKeysForUser(new_password, user.email); + + var data = {}; + data.current_password = current_keys.pw; + data.password = new_keys.pw; + data.password_confirmation = new_keys.pw; + + var user = this.user; + + this._performPasswordChange(current_keys, new_keys, function(response){ + if(response && !response.errors) { + // this.showNewPasswordForm = false; + if(user.local_encryption_enabled) { + // reencrypt data with new gk + this.reencryptAllNotesAndSave(user, new_keys.gk, current_keys.gk, function(success){ + if(success) { + this.setGk(new_keys.gk); + alert("Your password has been changed and your data re-encrypted."); + } else { + // rollback password + this._performPasswordChange(new_keys, current_keys, function(response){ + alert("There was an error changing your password. Your password has been rolled back."); + window.location.reload(); + }) + } + }.bind(this)); + } else { + alert("Your password has been changed."); + } + } else { + // this.showNewPasswordForm = false; + alert("There was an error changing your password. Please try again."); + } + }) + } + + this._performPasswordChange = function(email, current_keys, new_keys, callback) { + var request = Restangular.one("auth"); + request.user = {password: new_keys.pw, password_confirmation: new_keys.pw, current_password: current_keys.pw, email: email}; + request.patch().then(function(response){ + callback(response); + }) + } + + /* User */ @@ -171,14 +255,14 @@ angular.module('app.services') this.shareGroup = function(user, group, callback) { var shareFn = function() { - Restangular.one("users", user.id).one("groups", group.id).one("share").post() + Restangular.one("users", user.id).one("groups", group.id).one("presentations").post() .then(function(response){ - var obj = response.plain(); + var presentation = response.plain(); group.notes.forEach(function(note){ note.shared_via_group = true; }); - _.merge(group, {presentation: obj.presentation}); - callback(obj); + _.merge(group, {presentation: presentation}); + callback(presentation); }) } @@ -195,11 +279,12 @@ angular.module('app.services') } this.unshareGroup = function(user, group, callback) { - Restangular.one("users", user.id).one("groups", group.id).one("unshare").post() - .then(function(response){ - var obj = response.plain(); - _.merge(group, {presentation: obj.presentation}); - callback(obj); + 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); }) } @@ -212,40 +297,16 @@ angular.module('app.services') */ this.saveBatchNotes = function(user, notes, encryptionEnabled, callback) { - notes = _.cloneDeep(notes); - notes.forEach(function(note){ - if(encryptionEnabled && !note.isPublic()) { - note.content = null; - note.name = null; - } else { - note.local_encrypted_content = null; - note.local_eek = null; - } - }) - var request = Restangular.one("users", user.id).one("notes/batch_update"); - request.notes = notes; + request.notes = _.map(notes, function(note){ + return this.createRequestParamsFromNote(note, user); + }.bind(this)); request.put().then(function(response){ var success = response.plain().success; callback(success); }) } - this.preprocessNoteForSaving = function(note, user) { - if(user.local_encryption_enabled && !note.pending_share && !note.isPublic()) { - // encrypt - this.encryptSingleNote(note, this.retrieveGk()); - note.content = null; // dont send unencrypted content to server - note.name = null; - } - else { - // decrypt - note.local_encrypted_content = null; - note.local_eek = null; - note.local_encryption_scheme = null; - } - } - this.saveNote = function(user, note, callback) { if(!user.id) { this.writeUserToLocalStorage(user); @@ -253,18 +314,15 @@ angular.module('app.services') return; } - var snipCopy = _.cloneDeep(note); - - this.preprocessNoteForSaving(snipCopy, user); + var params = this.createRequestParamsFromNote(note, user); var request = Restangular.one("users", user.id).one("notes", note.id); - _.merge(request, snipCopy); - + _.merge(request, params); + console.log("saving note", request); request.customOperation(request.id ? "put" : "post") .then(function(response) { var responseObject = response.plain(); responseObject.content = note.content; - responseObject.name = note.name; _.merge(note, responseObject); callback(note); }) @@ -273,6 +331,26 @@ angular.module('app.services') }) } + this.createRequestParamsFromNote = function(note, user) { + var params = {}; + + if(user.local_encryption_enabled && !note.pending_share && !note.isPublic()) { + // encrypted + var noteCopy = _.cloneDeep(note); + this.encryptSingleNote(noteCopy, this.retrieveGk()); + + params.loc_enc_content = noteCopy.loc_enc_content; + params.loc_eek = noteCopy.loc_eek; + } + else { + // decrypted + params.content = note.JSONContent(); + } + + return params; + } + + this.deleteNote = function(user, note, callback) { if(!user.id) { this.writeUserToLocalStorage(user); @@ -289,10 +367,10 @@ angular.module('app.services') if(!user.id) { if(confirm("Note: You are not signed in. Any note you share cannot be edited or unshared.")) { var request = Restangular.one("notes").one("share"); - _.merge(request, {name: note.name, content: note.content}); + _.merge(request, {name: note.title, content: note.content}); request.post().then(function(response){ - var obj = response.plain(); - _.merge(note, {presentation: obj.presentation}); + var presentation = response.plain(); + _.merge(note, {presentation: presentation}); note.locked = true; this.writeUserToLocalStorage(user); callback(note); @@ -300,10 +378,10 @@ angular.module('app.services') } } else { var shareFn = function(note, callback) { - Restangular.one("users", user.id).one("notes", note.id).one("share").post() + Restangular.one("users", user.id).one("notes", note.id).one("presentations").post() .then(function(response){ - var obj = response.plain(); - _.merge(note, {presentation: obj.presentation}); + var presentation = response.plain(); + _.merge(note, {presentation: presentation}); callback(note); }) } @@ -322,10 +400,11 @@ angular.module('app.services') } this.unshareNote = function(user, note, callback) { - Restangular.one("users", user.id).one("notes", note.id).one("unshare").post() - .then(function(response){ - var obj = response.plain(); - _.merge(note, {presentation: obj.presentation}); + 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); }) } @@ -351,8 +430,8 @@ angular.module('app.services') var notes = _.map(user.filteredNotes(), function(note){ return { id: note.id, - name: note.name, - content: note.content, + title: note.title, + text: note.text, created_at: note.created_at, modified_at: note.modified_at, group_id: note.group_id @@ -455,20 +534,20 @@ angular.module('app.services') localStorage.setItem('gk', gk); } - this.clearGk = function() { + this.signout = function() { + localStorage.removeItem("jwt"); localStorage.removeItem("gk"); } this.encryptSingleNote = function(note, key) { var ek = null; if(note.isEncrypted()) { - ek = Neeto.crypto.decryptText(note.local_eek, key); + ek = Neeto.crypto.decryptText(note.loc_eek, key); } else { ek = Neeto.crypto.generateRandomEncryptionKey(); - note.local_eek = Neeto.crypto.encryptText(ek, key); + note.loc_eek = Neeto.crypto.encryptText(ek, key); } - var text = JSON.stringify({name: note.name, content: note.content}); - note.local_encrypted_content = Neeto.crypto.encryptText(text, ek); + note.loc_enc_content = Neeto.crypto.encryptText(note.JSONContent(), ek); note.local_encryption_scheme = "1.0"; } @@ -491,10 +570,9 @@ angular.module('app.services') } this.decryptSingleNote = function(note, key) { - var ek = Neeto.crypto.decryptText(note.local_eek, key); - var obj = JSON.parse(Neeto.crypto.decryptText(note.local_encrypted_content, ek)); - note.name = obj.name; - note.content = obj.content; + var ek = Neeto.crypto.decryptText(note.loc_eek || note.local_eek, key); + var content = Neeto.crypto.decryptText(note.loc_enc_content || note.local_encrypted_content, ek); + note.content = content; } this.decryptNotes = function(notes, key) { @@ -514,9 +592,9 @@ angular.module('app.services') notes.forEach(function(note){ if(note.isEncrypted()) { // first decrypt eek with old key - var ek = Neeto.crypto.decryptText(note.local_eek, oldKey); + var ek = Neeto.crypto.decryptText(note.loc_eek, oldKey); // now encrypt ek with new key - note.local_eek = Neeto.crypto.encryptText(ek, newKey); + note.loc_eek = Neeto.crypto.encryptText(ek, newKey); } }); diff --git a/app/assets/javascripts/app/services/directives/snippet.js b/app/assets/javascripts/app/services/directives/snippet.js index fa78e22c8..22939125b 100644 --- a/app/assets/javascripts/app/services/directives/snippet.js +++ b/app/assets/javascripts/app/services/directives/snippet.js @@ -12,6 +12,6 @@ angular }) .controller('SingleNoteCtrl', function ($rootScope, $scope, $state, markdownRenderer) { $scope.renderedContent = function() { - return markdownRenderer.renderHtml(markdownRenderer.renderedContentForText($scope.note.content)); + return markdownRenderer.renderHtml(markdownRenderer.renderedContentForText($scope.note.text)); } }); diff --git a/app/assets/templates/frontend/editor.html.haml b/app/assets/templates/frontend/editor.html.haml index 58679af63..bbfd6554e 100644 --- a/app/assets/templates/frontend/editor.html.haml +++ b/app/assets/templates/frontend/editor.html.haml @@ -2,7 +2,7 @@ .content .section-title-bar.editor-heading{"ng-class" => "{'shared' : ctrl.note.isPublic() }"} .title - %input.input#note-title-editor{"ng-model" => "ctrl.note.name", "ng-keyup" => "$event.keyCode == 13 && ctrl.saveTitle($event)", + %input.input#note-title-editor{"ng-model" => "ctrl.note.title", "ng-keyup" => "$event.keyCode == 13 && ctrl.saveTitle($event)", "ng-disabled" => "ctrl.note.locked", "ng-change" => "ctrl.nameChanged()", "ng-focus" => "ctrl.onNameFocus()", "select-on-click" => "true"} .save-status {{ctrl.noteStatus}} @@ -56,6 +56,6 @@ "iteration-callback" => "ctrl.callback", "prebegin-fn" => "ctrl.prebeginFn", "iteration-delay" => "2000", "cursor" => ""} %code{"ng-if" => "ctrl.currentDemoContent.text"} .content-sampler.sampler{"typewrite" => "true", "text" => "ctrl.currentDemoContent.text", "type-delay" => "10", "iteration-callback" => "ctrl.contentCallback"} - %textarea.editable#note-text-editor{"ng-disabled" => "ctrl.note.locked", "ng-show" => "ctrl.editorMode == 'edit'", "ng-model" => "ctrl.note.content", + %textarea.editable#note-text-editor{"ng-disabled" => "ctrl.note.locked", "ng-show" => "ctrl.editorMode == 'edit'", "ng-model" => "ctrl.note.text", "ng-change" => "ctrl.contentChanged()", "ng-click" => "ctrl.clickedTextArea()", "ng-focus" => "ctrl.onContentFocus()"} .preview{"ng-if" => "ctrl.editorMode == 'preview'", "ng-bind-html" => "ctrl.renderedContent()", "ng-dblclick" => "ctrl.onPreviewDoubleClick()"} diff --git a/app/assets/templates/frontend/notes.html.haml b/app/assets/templates/frontend/notes.html.haml index 11c280562..998ef4c30 100644 --- a/app/assets/templates/frontend/notes.html.haml +++ b/app/assets/templates/frontend/notes.html.haml @@ -34,5 +34,5 @@ "ng-click" => "ctrl.selectNote(note)", "ng-class" => "{'selected' : ctrl.selectedNote == note}", "ng-attr-draggable" => "{{note.dummy ? undefined : 'true'}}", "note" => "note"} .name - {{note.name}} + {{note.title}} .date {{note.created_at || 'Now'}} diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 2e56791c8..a5f79566b 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,4 +1,4 @@ # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password, :content, :name, :local_encrypted_content, :local_eek] +Rails.application.config.filter_parameters += [:password, :content, :name, :local_encrypted_content, :loc_eek]