api format, css, auth errors
This commit is contained in:
@@ -22,7 +22,7 @@ angular.module('app.frontend', [
|
||||
RestangularProvider.setDefaultHeaders({"Content-Type": "application/json"});
|
||||
|
||||
var url = apiControllerProvider.defaultServerURL();
|
||||
RestangularProvider.setBaseUrl(url);
|
||||
RestangularProvider.setBaseUrl(url + "/api");
|
||||
|
||||
RestangularProvider.setFullRequestInterceptor(function(element, operation, route, url, headers, params, httpConfig) {
|
||||
var token = localStorage.getItem("jwt");
|
||||
|
||||
@@ -73,9 +73,10 @@ angular.module('app.frontend')
|
||||
this.loginData.status = "Generating Login Keys...";
|
||||
$timeout(function(){
|
||||
apiController.login(this.loginData.email, this.loginData.user_password, function(response){
|
||||
if(response.errors) {
|
||||
console.log("login error", response.errors);
|
||||
this.loginData.status = response.errors[0];
|
||||
if(!response || response.error) {
|
||||
var error = response ? response.error : {message: "An unknown error occured."}
|
||||
this.loginData.status = null;
|
||||
alert(error.message);
|
||||
} else {
|
||||
this.onAuthSuccess(response.user);
|
||||
}
|
||||
@@ -88,8 +89,10 @@ angular.module('app.frontend')
|
||||
|
||||
$timeout(function(){
|
||||
apiController.register(this.loginData.email, this.loginData.user_password, function(response){
|
||||
if(response.errors) {
|
||||
this.loginData.status = response.errors[0];
|
||||
if(!response || response.error) {
|
||||
var error = response ? response.error : {message: "An unknown error occured."}
|
||||
this.loginData.status = null;
|
||||
alert(error.message);
|
||||
} else {
|
||||
this.onAuthSuccess(response.user);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ angular.module('app.frontend')
|
||||
$rootScope.title = "Notes — Standard Notes";
|
||||
onUserSet();
|
||||
} else {
|
||||
$scope.defaultUser = new User(apiController.localUser());
|
||||
$scope.defaultUser = new User(apiController.loadLocalItemsAndUser());
|
||||
onUserSet();
|
||||
}
|
||||
});
|
||||
@@ -141,7 +141,7 @@ angular.module('app.frontend')
|
||||
*/
|
||||
|
||||
$scope.headerLogout = function() {
|
||||
$scope.defaultUser = apiController.localUser();
|
||||
$scope.defaultUser = apiController.loadLocalItemsAndUser();
|
||||
$scope.tags = $scope.defaultUser.tags;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,14 @@ class Item {
|
||||
|
||||
_.merge(this, json_obj);
|
||||
|
||||
if(this.created_at) {
|
||||
this.created_at = new Date(this.created_at);
|
||||
this.updated_at = new Date(this.updated_at);
|
||||
} else {
|
||||
this.created_at = new Date();
|
||||
this.updated_at = new Date();
|
||||
}
|
||||
|
||||
if(!this.uuid) {
|
||||
this.uuid = Neeto.crypto.generateUUID();
|
||||
}
|
||||
@@ -43,6 +51,12 @@ class Item {
|
||||
}
|
||||
}
|
||||
|
||||
static sortItemsByDate(items) {
|
||||
items.sort(function(a,b){
|
||||
return new Date(b.created_at) - new Date(a.created_at);
|
||||
});
|
||||
}
|
||||
|
||||
addReference(reference) {
|
||||
this.content.references.push(reference);
|
||||
this.content.references = _.uniq(this.content.references);
|
||||
|
||||
@@ -62,6 +62,10 @@ angular.module('app.frontend')
|
||||
request.get({email: email}).then(function(response){
|
||||
callback(response.plain());
|
||||
})
|
||||
.catch(function(response){
|
||||
console.log("Error getting current user", response);
|
||||
callback(response.data);
|
||||
})
|
||||
}
|
||||
|
||||
this.getCurrentUser = function(callback) {
|
||||
@@ -77,22 +81,32 @@ angular.module('app.frontend')
|
||||
var user = _.omit(plain, ["items"]);
|
||||
callback(user, items);
|
||||
}.bind(this))
|
||||
.catch(function(error){
|
||||
console.log("Error getting current user", error);
|
||||
callback(null);
|
||||
.catch(function(response){
|
||||
console.log("Error getting current user", response);
|
||||
callback(response.data);
|
||||
})
|
||||
}
|
||||
|
||||
this.login = function(email, password, callback) {
|
||||
this.getAuthParamsForEmail(email, function(authParams){
|
||||
if(!authParams) {
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
Neeto.crypto.computeEncryptionKeysForUser(_.merge({email: email, password: password}, authParams), function(keys){
|
||||
this.setMk(keys.mk);
|
||||
var request = Restangular.one("auth/sign_in");
|
||||
request.user = {password: keys.pw, email: email};
|
||||
console.log("sending pw", keys.pw);
|
||||
var params = {password: keys.pw, email: email};
|
||||
_.merge(request, params);
|
||||
request.post().then(function(response){
|
||||
localStorage.setItem("jwt", response.token);
|
||||
callback(response);
|
||||
})
|
||||
.catch(function(response){
|
||||
console.log(response.data);
|
||||
callback(response.data);
|
||||
})
|
||||
}.bind(this));
|
||||
}.bind(this))
|
||||
}
|
||||
@@ -102,16 +116,25 @@ angular.module('app.frontend')
|
||||
this.setMk(keys.mk);
|
||||
keys.mk = null;
|
||||
var request = Restangular.one("auth");
|
||||
request.user = _.merge({password: keys.pw, email: email}, keys);
|
||||
var params = _.merge({password: keys.pw, email: email}, keys);
|
||||
_.merge(request, params);
|
||||
request.post().then(function(response){
|
||||
localStorage.setItem("jwt", response.token);
|
||||
callback(response);
|
||||
})
|
||||
.catch(function(response){
|
||||
console.log(response.data);
|
||||
callback(response.data);
|
||||
})
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
this.changePassword = function(user, current_password, new_password) {
|
||||
this.getAuthParamsForEmail(email, function(authParams){
|
||||
if(!authParams) {
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
Neeto.crypto.computeEncryptionKeysForUser(_.merge({password: current_password, email: user.email}, authParams), function(currentKeys) {
|
||||
Neeto.crypto.computeEncryptionKeysForUser(_.merge({password: new_password, email: user.email}, authParams), function(newKeys){
|
||||
var data = {};
|
||||
@@ -122,7 +145,7 @@ angular.module('app.frontend')
|
||||
var user = this.user;
|
||||
|
||||
this._performPasswordChange(currentKeys, newKeys, function(response){
|
||||
if(response && !response.errors) {
|
||||
if(response && !response.error) {
|
||||
// this.showNewPasswordForm = false;
|
||||
// reencrypt data with new mk
|
||||
this.reencryptAllItemsAndSave(user, newKeys.mk, currentKeys.mk, function(success){
|
||||
@@ -149,7 +172,8 @@ angular.module('app.frontend')
|
||||
|
||||
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};
|
||||
var params = {password: new_keys.pw, password_confirmation: new_keys.pw, current_password: current_keys.pw, email: email};
|
||||
_.merge(request, params);
|
||||
request.patch().then(function(response){
|
||||
callback(response);
|
||||
})
|
||||
@@ -417,10 +441,11 @@ angular.module('app.frontend')
|
||||
localStorage.setItem(key, angular.toJson(value));
|
||||
}
|
||||
|
||||
this.localUser = function() {
|
||||
this.loadLocalItemsAndUser = function() {
|
||||
var user = {};
|
||||
var items = JSON.parse(localStorage.getItem('items'));
|
||||
items = this.mapResponseItemsToLocalModels(items);
|
||||
Item.sortItemsByDate(items);
|
||||
modelManager.items = items;
|
||||
user.items = items;
|
||||
user.shouldMerge = true;
|
||||
|
||||
11
app/assets/javascripts/app/services/filters/appDate.js
Normal file
11
app/assets/javascripts/app/services/filters/appDate.js
Normal file
@@ -0,0 +1,11 @@
|
||||
angular.module('app.frontend')
|
||||
.filter('appDate', function ($filter) {
|
||||
return function (input) {
|
||||
return input ? $filter('date')(new Date(input), 'MM/dd/yyyy', 'UTC') : '';
|
||||
};
|
||||
})
|
||||
.filter('appDateTime', function ($filter) {
|
||||
return function (input) {
|
||||
return input ? $filter('date')(new Date(input), 'MM/dd/yyyy h:mm a') : '';
|
||||
};
|
||||
});
|
||||
@@ -62,9 +62,7 @@ class ModelManager extends ItemManager {
|
||||
|
||||
refreshRelationshipsForTag(tag) {
|
||||
tag.notes = tag.referencesMatchingContentType("Note");
|
||||
tag.notes.sort(function(a,b){
|
||||
return new Date(b.created_at) - new Date(a.created_at);
|
||||
});
|
||||
Item.sortItemsByDate(tag.notes);
|
||||
}
|
||||
|
||||
refreshRelationshipsForNote(note) {
|
||||
|
||||
@@ -98,10 +98,20 @@
|
||||
|
||||
.item.account {
|
||||
|
||||
.email {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.link-item {
|
||||
margin-bottom: 8px;
|
||||
a {
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
color: #00228f;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -141,16 +151,22 @@
|
||||
}
|
||||
|
||||
> .action-container {
|
||||
font-size: 12px;
|
||||
margin-top: 6px;
|
||||
.status-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
font-size: 12px;
|
||||
margin-top: 6px;
|
||||
|
||||
.subtext {
|
||||
font-size: 10px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.status-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.subtext {
|
||||
font-size: 10px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
.encryption-confirmation {
|
||||
@@ -186,7 +202,6 @@
|
||||
> .desc {
|
||||
font-size: 12px;
|
||||
margin-top: 3px;
|
||||
// line-height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,6 +213,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
a.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.account-form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
@@ -214,8 +233,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.account-menu {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
|
||||
> .date {
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
|
||||
@@ -50,39 +50,42 @@
|
||||
{{ctrl.resetData.response}}
|
||||
|
||||
.account-item{"ng-if" => "ctrl.user.email"}
|
||||
.email {{ctrl.user.email}}
|
||||
.links{"ng-if" => "ctrl.user.email"}
|
||||
.link-item
|
||||
%a{"ng-click" => "ctrl.changePasswordPressed()"} Change Password
|
||||
%form.account-form{"ng-if" => "ctrl.showNewPasswordForm", 'ng-submit' => 'ctrl.submitPasswordChange()', 'name' => "passwordChangeForm"}
|
||||
.form-tag.has-feedback
|
||||
%input.form-control.login-input{:autofocus => 'autofocus', :name => 'current', :placeholder => 'Current password', :required => true, :type => 'password', 'ng-model' => 'ctrl.passwordChangeData.current_password'}
|
||||
.form-tag.has-feedback
|
||||
%input.form-control.login-input{:placeholder => 'New password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'ctrl.passwordChangeData.new_password', "autocomplete" => "new-password"}
|
||||
.form-tag.has-feedback
|
||||
%input.form-control.login-input{:placeholder => 'Confirm password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'ctrl.passwordChangeData.new_password_confirmation', "autocomplete" => "new-password"}
|
||||
%button.btn.dark-button.btn-block{:type => 'submit', "data-style" => "expand-right", "data-size" => "s", "state" => "buttonState"}
|
||||
%span.ladda-label Change Password
|
||||
.panel-status-text{"ng-if" => "ctrl.passwordChangeData.status", "style" => "font-size: 14px;"}
|
||||
{{ctrl.passwordChangeData.status}}
|
||||
.link-item
|
||||
%a{"ng-click" => "ctrl.signOutPressed()"} Sign Out
|
||||
.meta-container
|
||||
.title Local Encryption
|
||||
.desc Encrypt notes locally before sending to server. Neither the server owner nor an intruder can decrypt your locally encrypted notes.
|
||||
.action-container
|
||||
%span.status-title Status: enabled.
|
||||
%span.status-title Status:
|
||||
{{ctrl.encryptionStatusForNotes()}} (shared notes not encrypted)
|
||||
.account-item{"ng-if" => "ctrl.user.email"}
|
||||
.meta-container
|
||||
.title Data Archives
|
||||
.desc Note: data archives that you download using the link below are decrypted before save. You should take care to store them in a safe location.
|
||||
.action-container
|
||||
%a#download-archive{"ng-click" => "ctrl.downloadDataArchive()"} Download Latest Data Archive
|
||||
%a{"ng-click" => "ctrl.downloadDataArchive()"} Download Latest Data Archive
|
||||
%br
|
||||
%label#import-archive
|
||||
%input{"type" => "file", "style" => "display: none;", "file-change" => "", "handler" => "ctrl.importFileSelected(files)"}
|
||||
%span
|
||||
Import Data from Archive
|
||||
%input{"type" => "file", "style" => "display: none;", "file-change" => "->", "handler" => "ctrl.importFileSelected(files)"}
|
||||
%a.disabled
|
||||
%span
|
||||
Import Data from Archive
|
||||
|
||||
.links{"ng-if" => "ctrl.user.email"}
|
||||
.link-item
|
||||
%a{"ng-click" => "ctrl.changePasswordPressed()"} Change Password
|
||||
%form.account-form{"ng-if" => "ctrl.showNewPasswordForm", 'ng-submit' => 'ctrl.submitPasswordChange()', 'name' => "passwordChangeForm"}
|
||||
.form-tag.has-feedback
|
||||
%input.form-control.login-input{:autofocus => 'autofocus', :name => 'current', :placeholder => 'Current password', :required => true, :type => 'password', 'ng-model' => 'ctrl.passwordChangeData.current_password'}
|
||||
.form-tag.has-feedback
|
||||
%input.form-control.login-input{:placeholder => 'New password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'ctrl.passwordChangeData.new_password', "autocomplete" => "new-password"}
|
||||
.form-tag.has-feedback
|
||||
%input.form-control.login-input{:placeholder => 'Confirm password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'ctrl.passwordChangeData.new_password_confirmation', "autocomplete" => "new-password"}
|
||||
%button.btn.dark-button.btn-block{:type => 'submit', "data-style" => "expand-right", "data-size" => "s", "state" => "buttonState"}
|
||||
%span.ladda-label Change Password
|
||||
.panel-status-text{"ng-if" => "ctrl.passwordChangeData.status", "style" => "font-size: 14px;"}
|
||||
{{ctrl.passwordChangeData.status}}
|
||||
.link-item
|
||||
%a{"ng-click" => "ctrl.signOutPressed()"} Sign Out
|
||||
|
||||
.item
|
||||
%a{"href" => "https://standardnotes.org", "target" => "_blank"}
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
"ng-attr-draggable" => "{{note.dummy ? undefined : 'true'}}", "note" => "note"}
|
||||
.name
|
||||
{{note.content.title}}
|
||||
.date {{note.created_at || 'Now'}}
|
||||
.date {{(note.created_at | appDateTime) || 'Now'}}
|
||||
|
||||
Reference in New Issue
Block a user