Filtering with tags work, add oc notificaton service

This commit is contained in:
brantje 2016-09-16 14:01:25 +02:00
parent 2fc84e2a7b
commit 8d0f70f357
19 changed files with 462 additions and 125 deletions

View file

@ -89,6 +89,7 @@ class CredentialController extends ApiController {
'description' => $description,
'created' => $created,
'changed' => $changed,
'vault_id' => $vault_id,
'tags' => $tags,
'email' => $email,
'username' => $username,
@ -99,6 +100,8 @@ class CredentialController extends ApiController {
'expire_time' => $expire_time,
'files' => $files,
'custom_fields' => $custom_fields,
'delete_time' => $delete_time,
'hidden' => $hidden,
'otp' => $otp,
);
$credential = $this->credentialService->updateCredential($credential);

View file

@ -56,7 +56,7 @@
.pw-gen {
overflow: hidden; }
.pw-gen input {
width: calc(100% - 76px) !important;
width: calc(100% - 80px) !important;
float: left;
background: #fff;
color: #555;
@ -163,6 +163,10 @@
right: inherit;
left: 10px;
top: -19px; }
#app-content #app-content-wrapper .actions.creatable .title {
width: calc( 100% - 185px);
text-align: center;
display: inline-block; }
#app-content #app-content-wrapper .credential-table {
width: 100%;
margin-top: 44px; }
@ -287,8 +291,15 @@
padding: 2px;
width: auto;
white-space: nowrap;
height: 20px;
height: 25px;
vertical-align: middle; }
#app-content #app-content-wrapper .app_sidebar .tags {
margin-top: 15px;
margin-bottom: 15px; }
#app-content #app-content-wrapper .app_sidebar .tags .tag {
background-color: rgba(240, 240, 240, 0.9);
padding: 4px;
margin-right: 3px; }
.credential_field {
overflow: hidden; }
@ -305,6 +316,28 @@
.settings-container div {
padding-left: 15px; }
.nav-trashbin {
position: fixed !important;
bottom: 44px;
width: inherit !important;
background-color: #fff;
border-right: 1px solid #eee; }
.nav-trashbin a {
padding: 0 20px; }
.nav-trashbin a .fa {
margin-right: 15px; }
#app-navigation li a.taginput {
opacity: 1; }
#app-navigation li a {
overflow: visible; }
#app-navigation li a tags-input {
opacity: 1.0; }
#app-navigation li a tags-input li {
width: auto !important; }
#app-navigation > ul ul {
display: inherit !important; }
#app-settings-content:not(.ng-hide) {
height: 60px;
display: inherit !important;

File diff suppressed because one or more lines are too long

View file

@ -51,3 +51,30 @@ angular
localStorageServiceProvider
.setNotify(true, true);
});
/**
* jQuery for notification handling D:
**/
jQuery(document).ready(function () {
var findItemByID = function(id){
var credentials,foundItem=false;
credentials = angular.element('#app-content-wrapper').scope().credentials;
console.log(id, credentials)
angular.forEach(credentials, function(credential){
if(credential.credential_id == id){
foundItem = credential;
}
});
return foundItem;
};
jQuery(document).on('click', '.undoDelete', function () {
var credential = findItemByID($(this).attr('data-item-id'));
angular.element('#app-content-wrapper').scope().recoverCredential(credential);
angular.element('#app-content-wrapper').scope().$apply();
});
jQuery(document).on('click', '.undoRestore', function () {
var credential = findItemByID($(this).attr('data-item-id'));
angular.element('#app-content-wrapper').scope().deleteCredential(credential);
angular.element('#app-content-wrapper').scope().$apply();
});
});

View file

@ -8,92 +8,179 @@
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('CredentialCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', 'CredentialService', '$rootScope', 'FileService', 'EncryptService', 'TagService', function ($scope, VaultService, SettingsService, $location, CredentialService, $rootScope, FileService, EncryptService, TagService) {
$scope.active_vault = VaultService.getActiveVault();
if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
if (!$scope.active_vault) {
$location.path('/')
}
} else {
if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {
var _vault = angular.copy(SettingsService.getSetting('defaultVault'));
_vault.vaultKey = angular.copy(SettingsService.getSetting('defaultVaultPass'));
VaultService.setActiveVault(_vault);
$scope.active_vault = _vault;
//@TODO check if vault exists
.controller('CredentialCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', 'CredentialService',
'$rootScope', 'FileService', 'EncryptService', 'TagService', '$timeout', 'NotificationService',
function ($scope, VaultService, SettingsService, $location, CredentialService, $rootScope, FileService, EncryptService, TagService, $timeout, NotificationService) {
$scope.active_vault = VaultService.getActiveVault();
if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
if (!$scope.active_vault) {
$location.path('/')
}
} else {
if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {
var _vault = angular.copy(SettingsService.getSetting('defaultVault'));
_vault.vaultKey = angular.copy(SettingsService.getSetting('defaultVaultPass'));
VaultService.setActiveVault(_vault);
$scope.active_vault = _vault;
//@TODO check if vault exists
}
}
}
$scope.addCredential = function () {
var new_credential = CredentialService.newCredential();
var enc_c = CredentialService.encryptCredential(new_credential);
SettingsService.setSetting('edit_credential', enc_c);
$location.path('/vault/' + $scope.active_vault.vault_id + '/new')
};
$scope.addCredential = function(){
var new_credential = CredentialService.newCredential();
var enc_c = CredentialService.encryptCredential(new_credential);
SettingsService.setSetting('edit_credential',enc_c);
$location.path('/vault/'+ $scope.active_vault.vault_id +'/new')
};
$scope.editCredential = function (credential) {
var _credential = angular.copy(credential);
$rootScope.$emit('app_menu', false);
SettingsService.setSetting('edit_credential', CredentialService.encryptCredential(_credential));
$location.path('/vault/' + $scope.active_vault.vault_id + '/edit/' + _credential.credential_id)
};
$scope.editCredential = function(credential){
var _credential = angular.copy(credential);
$rootScope.$emit('app_menu', false);
SettingsService.setSetting('edit_credential', CredentialService.encryptCredential(_credential));
$location.path('/vault/'+ $scope.active_vault.vault_id +'/edit/'+ _credential.credential_id)
};
var notification;
$scope.deleteCredential = function (credential) {
var _credential = angular.copy(credential);
try {
_credential = CredentialService.decryptCredential(angular.copy(credential));
} catch (e) {
$scope.selectedCredential = false;
$scope.selectCredential = function (credential) {
$scope.selectedCredential = CredentialService.decryptCredential(angular.copy(credential));
$rootScope.$emit('app_menu', true);
};
}
_credential.delete_time = new Date().getTime() / 1000;
for (var i = 0; i < $scope.credentials.length; i++) {
if ($scope.credentials[i].credential_id == credential.credential_id) {
$scope.credentials[i].delete_time = _credential.delete_time;
}
}
$scope.closeSelected();
if (notification) {
NotificationService.hideNotification(notification);
}
notification = NotificationService.showNotification('Credential deleted <a class="undoDelete" data-item-id="' + credential.credential_id + '">[Undo]</a>', 5000,
function () {
CredentialService.updateCredential(_credential).then(function (result) {
if (result.delete_time > 0) {
notification = false;
}
});
});
};
$scope.recoverCredential = function (credential) {
var _credential = angular.copy(credential);
try {
_credential = CredentialService.decryptCredential(angular.copy(credential));
} catch (e) {
}
for (var i = 0; i < $scope.credentials.length; i++) {
if ($scope.credentials[i].credential_id == credential.credential_id) {
$scope.credentials[i].delete_time = 0;
}
}
_credential.delete_time = 0;
$scope.closeSelected();
if (notification) {
NotificationService.hideNotification(notification);
}
NotificationService.showNotification('Credential recovered <a class="undoRestore" data-item-id="' + credential.credential_id + '">[Undo]</a>', 7500,
function () {
CredentialService.updateCredential(_credential).then(function (result) {
notification = false;
});
});
};
$scope.itemFilter = {
label: ''
};
$scope.selectedtags = [];
$rootScope.$on('selected_tags_updated', function (evt, _sTags) {
var _selectedTags = []
for(var x = 0; x < _sTags.length; x++){
_selectedTags.push(_sTags[x].text)
}
console.log(_selectedTags)
$scope.selectedtags = _selectedTags;
});
$scope.delete_time = 0;
$scope.showCredentialRow = function (credential) {
if ($scope.delete_time == 0) {
return credential.delete_time == 0
} else {
return credential.delete_time > $scope.delete_time;
}
};
$rootScope.$on('set_delete_time', function (event, time) {
$scope.delete_time = time;
});
$scope.setDeleteTime = function (delete_time) {
$scope.delete_time = delete_time;
};
$scope.closeSelected = function () {
$rootScope.$emit('app_menu', false);
$scope.selectedCredential = false;
};
$scope.selectCredential = function (credential) {
$scope.selectedCredential = CredentialService.decryptCredential(angular.copy(credential));
$rootScope.$emit('app_menu', true);
};
$rootScope.$on('logout', function () {
console.log('Logout received, clean up');
$scope.credentials = [];
if ($scope.hasOwnProperty('$parent')) {
if ($scope.$parent.hasOwnProperty('selectedVault')) {
$scope.$parent.selectedVault = false;
$scope.closeSelected = function () {
$rootScope.$emit('app_menu', false);
$scope.selectedCredential = false;
};
$rootScope.$on('logout', function () {
console.log('Logout received, clean up');
$scope.credentials = [];
if ($scope.hasOwnProperty('$parent')) {
if ($scope.$parent.hasOwnProperty('selectedVault')) {
$scope.$parent.selectedVault = false;
}
}
$scope.active_vault = null;
});
var fetchCredentials = function () {
VaultService.getVault($scope.active_vault).then(function (credentials) {
var _credentials = [];
for (var i = 0; i < credentials.length; i++) {
var credential = angular.copy(credentials[i]);
var _tags = CredentialService.decryptCredential(angular.copy(credentials[i])).tags;
TagService.addTags(_tags);
credential.tags_raw = _tags;
_credentials.push(credential);
}
$scope.credentials = _credentials;
});
};
$scope.downloadFile = function (file) {
FileService.getFile(file).then(function (result) {
var file_data = EncryptService.decryptString(result.file_data);
var uriContent = FileService.dataURItoBlob(file_data, file.mimetype), a = document.createElement("a");
a.style = "display: none";
a.href = uriContent;
a.download = escapeHTML(file.filename);
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(uriContent);
});
};
if ($scope.active_vault) {
$scope.$parent.selectedVault = true;
fetchCredentials();
}
$scope.active_vault = null;
});
var fetchCredentials = function () {
VaultService.getVault($scope.active_vault).then(function (credentials) {
var _credentials = [];
for (var i = 0; i < credentials.length; i++) {
var credential = angular.copy(credentials[i]);
var _tags = CredentialService.decryptCredential(angular.copy(credentials[i])).tags;
TagService.addTags(_tags)
credential.tags_raw = _tags;
_credentials.push(credential);
}
$scope.credentials = _credentials;
});
};
$scope.downloadFile = function (file) {
FileService.getFile(file).then(function (result) {
var file_data = EncryptService.decryptString(result.file_data);
var uriContent = FileService.dataURItoBlob(file_data, file.mimetype), a = document.createElement("a");
a.style = "display: none";
a.href = uriContent;
a.download = escapeHTML(file.filename);
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(uriContent);
});
};
//@TODO TagService which holds all the tags
//@TODO Show otp field
if ($scope.active_vault) {
$scope.$parent.selectedVault = true;
fetchCredentials();
}
}]);
}]);

View file

@ -8,7 +8,8 @@
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', 'TagService', function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService, TagService) {
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', 'TagService', 'NotificationService',
function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService, TagService, NotificationService) {
$scope.active_vault = VaultService.getActiveVault();
@ -105,12 +106,10 @@ angular.module('passmanApp')
$scope.addCustomField = function () {
if (!$scope.new_custom_field.label) {
//@TODO move OC.Notification to a service
OC.Notification.showTemporary('Please fill in a label');
NotificationService.showNotification('Please fill in a label', 3000);
}
if (!$scope.new_custom_field.value) {
//@TODO move OC.Notification to a service
OC.Notification.showTemporary('Please fill in a value!');
NotificationService.showNotification('Please fill in a value!', 3000);
}
if (!$scope.new_custom_field.label || !$scope.new_custom_field.value) {
return;
@ -166,7 +165,7 @@ angular.module('passmanApp')
}
};
//@TODO Set tags, read them from tag service
$scope.parseQR = function(QRCode){
var re = /otpauth:\/\/(totp|hotp)\/(.*)\?(secret|issuer)=(.*)&(issuer|secret)=(.*)/, parsedQR,qrInfo;
@ -191,13 +190,13 @@ angular.module('passmanApp')
$scope.storedCredential.vault_id = $scope.active_vault.vault_id;
CredentialService.createCredential($scope.storedCredential).then(function (result) {
$location.path('/vault/' + $routeParams.vault_id);
//@TODO Show notification
NotificationService.showNotification('Credential created!', 5000)
})
} else {
CredentialService.updateCredential($scope.storedCredential).then(function (result) {
SettingsService.setSetting('edit_credential', null);
$location.path('/vault/' + $routeParams.vault_id);
//@TODO Show notification
NotificationService.showNotification('Credential updated!', 5000)
})
}
};

View file

@ -8,10 +8,42 @@
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('MenuCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', '$rootScope', function ($scope, VaultService, SettingsService, $location, $rootScope) {
$scope.logout = function () {
SettingsService.setSetting('defaultVaultPass', false);
$rootScope.$broadcast('logout');
$location.path('/');
}
}]);
.controller('MenuCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', '$rootScope', 'TagService',
function ($scope, VaultService, SettingsService, $location, $rootScope, TagService) {
$scope.logout = function () {
SettingsService.setSetting('defaultVaultPass', false);
$rootScope.$broadcast('logout');
$location.path('/');
};
$scope.selectedTags = [];
$scope.getTags = function ($query) {
console.log(TagService.searchTag($query));
return TagService.searchTag($query);
};
$scope.$watch('selectedTags', function () {
$rootScope.$broadcast('selected_tags_updated', $scope.selectedTags)
}, true);
$scope.tagClicked = function (tag) {
$scope.selectedTags.push(tag)
};
$scope.available_tags = TagService.getTags();
$scope.$watch(function () {
return TagService.getTags();
}, function (tags) {
$scope.available_tags = tags;
}, true);
$scope.toggleDeleteTime = function () {
if ($scope.delete_time > 0) {
$scope.delete_time = 0;
} else {
$scope.delete_time = 1;
}
$rootScope.$broadcast('set_delete_time', $scope.delete_time);
};
}]);

View file

@ -41,10 +41,12 @@ angular.module('passmanApp')
}
return {
restrict: 'A',
template: '<span class="otp_generator"><span credential-field value="otp" secret="\'true\'"></span> <span ng-bind="timeleft"></span></span>',
transclude: false,
scope: {
secret: '='
},
replace: true,
link: function (scope, element) {
scope.otp = null;
scope.timeleft = null;
@ -82,10 +84,6 @@ angular.module('passmanApp')
$timeout.cancel(scope.timer);
}
}, true);
//@TODO FIX THIS UGLY SHIT
var html = '<span pw="otp">{{otp}}</span> Time left: <span ng-bind="timeleft"></span>';
element.html($compile(html)(scope));
scope.$on(
"$destroy",
function (event) {

View file

@ -0,0 +1,31 @@
'use strict';
/**
* @ngdoc filter
* @name passmanApp.filter:selectedTags
* @function
* @description
* # selectedTags
* Filter in the passmanApp.
*/
angular.module('passmanApp')
.filter('tagFilter', function() {
return function(credentials, tags) {
var _credentials = [];
if(tags.length > 0) {
for (var ci = 0; ci < credentials.length; ci++) {
var c = credentials[ci];
for (var ct = 0; ct < c.tags_raw.length; ct++) {
var t = c.tags_raw[ct];
if(tags.indexOf(t.text) != -1){
_credentials.push(c);
}
}
}
}
if(tags.length == 0){
_credentials = credentials;
}
return _credentials;
};
});

View file

@ -0,0 +1,29 @@
'use strict';
/**
* @ngdoc service
* @name passmanApp.NotificationService
* @description
* # NotificationService
* Service in the passmanApp.
*/
angular.module('passmanApp')
.service('NotificationService', ['$timeout', function ($timeout) {
var to ;
return {
showNotification: function (text, time, closeCallback) {
var notification = OC.Notification.showHtml(text);
to =$timeout(function () {
OC.Notification.hide(notification, closeCallback)
}, time);
return notification;
},
hideNotification: function (notification) {
$timeout.cancel(to);
OC.Notification.hide(notification)
},
hideAll: function () {
OC.Notification.hide();
}
}
}]);

View file

@ -19,8 +19,8 @@ angular.module('passmanApp')
},
addTags: function (tags) {
for(var i =0; i < tags.length; i++){
if(_tags.indexOf(tags[i]) == -1){
_tags.push(tags[i]);
if( $filter('filter')(_tags,{text: tags[i].text }).length == 0){
_tags.push(tags[i])
}
}
},

View file

@ -23,7 +23,7 @@ angular.module('views/partials/forms/edit_credential/custom_fields.html', []).ru
angular.module('views/partials/forms/edit_credential/files.html', []).run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('views/partials/forms/edit_credential/files.html',
'<div class="row file_tab"><div class="col-xs-12 col-md-6"><input type="file" file-select success="fileLoaded" error="fileLoadError" progress="fileSelectProgress"> <span ng-if="fileprogress.file_percent > 0"><div progress-bar="fileprogress.file_percent"></div></span></div></div><div class="row files" ng-if="storedCredential.files.length > 0"><div class="col-xs-12 table"><table><thead use-theme><tr><th class="field_label">Filename</th><th class="field_value">Upload date</th><th class="field_secret">Size</th><th class="field_actions">Actions</th></tr></thead><tr ng-repeat="file in storedCredential.files"><td><a href="#" editable-text="file.filename">{{ file.filename || "empty" }}</a></td><td>{{file.created}}</td><td>{{file.size | bytes}}</td><td class="field_actions"><i class="fa fa-trash" ng-click="deleteFile(file)"></i></td></tr></table></div></div>');
'<div class="row file_tab"><div class="col-xs-12 col-md-6"><input type="file" file-select success="fileLoaded" error="fileLoadError" progress="fileSelectProgress"> <span ng-if="fileprogress.file_percent > 0"><div progress-bar="fileprogress.file_percent"></div></span></div></div><div class="row files" ng-if="storedCredential.files.length > 0"><div class="col-xs-12 table"><table><thead use-theme><tr><th class="field_label">Filename</th><th class="field_value">Upload date</th><th class="field_secret">Size</th><th class="field_actions">Actions</th></tr></thead><tr ng-repeat="file in storedCredential.files"><td><a href="#" editable-text="file.filename">{{ file.filename || "empty" }}</a></td><td>{{file.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td><td>{{file.size | bytes}}</td><td class="field_actions"><i class="fa fa-trash" ng-click="deleteFile(file)"></i></td></tr></table></div></div>');
}]);
angular.module('views/partials/forms/edit_credential/otp.html', []).run(['$templateCache', function($templateCache) {
@ -47,7 +47,7 @@ angular.module('views/partials/password-meter.html', []).run(['$templateCache',
angular.module('views/show_vault.html', []).run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('views/show_vault.html',
'<div id="controls"><div class="breadcrumb"></div><div class="actions creatable"><span ng-click="menuOpen = !menuOpen" class="button new" ng-init="menuOpen = false" off-click="menuOpen = false;"><span>New</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li><span ng-click="addCredential()" class="menuitem action"><span class="icon icon-rename"></span> <span>New credential</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-shared"></span> <span>New shared credential</span></span></li></ul></div></div></div><div off-click="closeSelected()"><table class="credential-table" ng-init="menuOpen = false;"><tr ng-repeat="credential in credentials" ng-if="credential.hidden == 0 && credential.delete_time == 0" ng-click="selectCredential(credential)" ng-class="{\'selected\': selectedCredential.credential_id == credential.credential_id}"><td><span class="label">{{credential.label}}</span> <span class="tags"><span class="tag" ng-repeat="tag in credential.tags_raw">{{tag.text}}</span></span></td></tr></table><div id="app-sidebar" class="detailsView scroll-container app_sidebar" ng-show="selectedCredential"><span class="close icon-close" ng-click="closeSelected()" alt="Close"></span><table><tr ng-show="selectedCredential.label"><td>Label</td><td>{{selectedCredential.label}}</td></tr><tr ng-show="selectedCredential.username"><td>Account</td><td><span credential-field value="selectedCredential.username"></span></td></tr><tr ng-show="selectedCredential.password"><td>Password</td><td><span credential-field value="selectedCredential.password" secret="\'true\'"></span></td></tr><tr ng-show="selectedCredential.email"><td>E-mail</td><td><span credential-field value="selectedCredential.email"></span></td></tr><tr ng-show="selectedCredential.url"><td>URL</td><td><span credential-field value="selectedCredential.url"></span></td></tr><tr ng-show="selectedCredential.files.length > 0"><td>Files</td><td><div ng-repeat="file in selectedCredential.files" class="link" ng-click="downloadFile(file)">{{file.filename}} ({{file.size | bytes}})</div></td></tr><tr ng-repeat="field in selectedCredential.custom_fields"><td>{{field.label}}</td><td><span credential-field value="field.value" secret="field.secret"></span></td></tr><tr ng-show="selectedCredential.changed"><td>Changed</td><td>{{selectedCredential.changed * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr><tr ng-show="selectedCredential.created"><td>Created</td><td>{{selectedCredential.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr></table><div ng-show="selectedCredential"><span class="button" ng-click="editCredential(selectedCredential)"><span class="fa fa-edit"></span> Edit</span> <span class="button"><span class="fa fa-trash"></span> Delete</span> <span class="button"><span class="fa fa-share"></span> Share</span></div></div></div>');
'<div id="controls"><div class="breadcrumb"></div><div class="actions creatable"><span ng-click="menuOpen = !menuOpen" class="button new" ng-init="menuOpen = false" off-click="menuOpen = false;"><span>New</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li><span ng-click="addCredential()" class="menuitem action"><span class="icon icon-rename"></span> <span>New credential</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-shared"></span> <span>New shared credential</span></span></li></ul></div><input type="text" ng-model="itemFilter.label"> <span class="title" ng-if="delete_time">Showing deleted since: <span ng-if="delete_time == 1">All time</span> <span ng-if="delete_time > 1">{{delete_time | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</span></span></div></div><div off-click="closeSelected()"><table class="credential-table" ng-init="menuOpen = false;"><tr ng-repeat="credential in credentials | filter:itemFilter | tagFilter:selectedtags" ng-if="credential.hidden == 0 && showCredentialRow(credential)" ng-click="selectCredential(credential)" ng-class="{\'selected\': selectedCredential.credential_id == credential.credential_id}"><td><span class="label">{{credential.label}}</span> <span class="tags"><span class="tag" ng-repeat="tag in credential.tags_raw">{{tag.text}}</span></span></td></tr></table><div id="app-sidebar" class="detailsView scroll-container app_sidebar" ng-show="selectedCredential"><span class="close icon-close" ng-click="closeSelected()" alt="Close"></span><table><tr ng-show="selectedCredential.label"><td>Label</td><td>{{selectedCredential.label}}</td></tr><tr ng-show="selectedCredential.username"><td>Account</td><td><span credential-field value="selectedCredential.username"></span></td></tr><tr ng-show="selectedCredential.password"><td>Password</td><td><span credential-field value="selectedCredential.password" secret="\'true\'"></span></td></tr><tr ng-show="selectedCredential.otp.secret"><td>OTP</td><td><span otp-generator secret="selectedCredential.otp.secret"></span></td></tr><tr ng-show="selectedCredential.email"><td>E-mail</td><td><span credential-field value="selectedCredential.email"></span></td></tr><tr ng-show="selectedCredential.url"><td>URL</td><td><span credential-field value="selectedCredential.url"></span></td></tr><tr ng-show="selectedCredential.files.length > 0"><td>Files</td><td><div ng-repeat="file in selectedCredential.files" class="link" ng-click="downloadFile(file)">{{file.filename}} ({{file.size | bytes}})</div></td></tr><tr ng-repeat="field in selectedCredential.custom_fields"><td>{{field.label}}</td><td><span credential-field value="field.value" secret="field.secret"></span></td></tr><tr ng-show="selectedCredential.changed"><td>Changed</td><td>{{selectedCredential.changed * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr><tr ng-show="selectedCredential.created"><td>Created</td><td>{{selectedCredential.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr></table><div class="tags"><span class="tag" ng-repeat="tag in selectedCredential.tags">{{tag.text}}</span></div><div ng-show="selectedCredential"><span class="button" ng-click="editCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0"><span class="fa fa-edit"></span> Edit</span> <span class="button" ng-click="deleteCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0"><span class="fa fa-trash"></span> Delete</span> <span class="button" ng-if="selectedCredential.delete_time > 0" ng-click="recoverCredential(selectedCredential)"><span class="fa fa-recycle"></span> Recover</span> <span class="button" ng-if="selectedCredential.delete_time == 0"><span class="fa fa-share"></span> Share</span></div></div></div>');
}]);
angular.module('views/vaults.html', []).run(['$templateCache', function($templateCache) {

View file

@ -59,11 +59,20 @@ class CredentialMapper extends Mapper {
}
public function update($raw_credential){
if(!$raw_credential['guid']){
$raw_credential['guid'] = $this->utils->GUID();
}
if(!$raw_credential['created']){
$raw_credential['created'] = $this->utils->getTime();
}
$credential = new Credential();
$credential->setId($raw_credential['credential_id']);
$credential->setGuid($raw_credential['guid']);
$credential->setVaultId($raw_credential['vault_id']);
$credential->setUserId($raw_credential['user_id']);
$credential->setLabel($raw_credential['label']);
$credential->setDescription($raw_credential['description']);
$credential->setCreated($raw_credential['created']);
$credential->setChanged($this->utils->getTime());
$credential->setTags($raw_credential['tags']);
$credential->setEmail($raw_credential['email']);
@ -77,6 +86,7 @@ class CredentialMapper extends Mapper {
$credential->setCustomFields($raw_credential['custom_fields']);
$credential->setOtp($raw_credential['otp']);
$credential->setHidden($raw_credential['hidden']);
$credential->setDeleteTime($raw_credential['delete_time']);
return parent::update($credential);
}

View file

@ -24,6 +24,11 @@
left: 10px;
top: -19px;
}
.title{
width: calc( 100% - 185px);
text-align: center;
display: inline-block;
}
}
.credential-table {
width: 100%;
@ -208,11 +213,21 @@
padding: 2px;
width: auto;
white-space: nowrap;
height: 20px;
height: 25px;
vertical-align: middle;
}
}
}
.tags {
margin-top: 15px;
margin-bottom: 15px;
.tag {
background-color: rgba(240, 240, 240, .9);
padding: 4px;
margin-right: 3px;
}
}
}
}

View file

@ -1,6 +1,40 @@
.settings-container{
div{
.settings-container {
div {
padding-left: 15px;
}
}
.nav-trashbin {
position: fixed !important;
bottom: 44px;
width: inherit !important;
background-color: #fff;
border-right: 1px solid #eee;
a {
padding: 0 20px;
.fa {
margin-right: 15px;
}
}
}
#app-navigation {
li{
a.taginput{
opacity: 1;
}
a{
overflow: visible;
tags-input{
opacity: 1.0;
li{
width: auto !important;
}
}
}
}
> ul ul {
display: inherit !important;
}
}

View file

@ -1,7 +1,7 @@
.pw-gen{
overflow:hidden;
input{
width: calc(100% - 76px) !important;
width: calc(100% - 80px) !important;
float: left;
background: #fff;
color: #555;

View file

@ -32,6 +32,7 @@ script('passman', 'app/controllers/edit_credential');
script('passman', 'app/filters/range');
script('passman', 'app/filters/propsfilter');
script('passman', 'app/filters/byte');
script('passman', 'app/filters/tagfilter');
script('passman', 'app/services/cacheservice');
script('passman', 'app/services/vaultservice');
script('passman', 'app/services/credentialservice');
@ -39,6 +40,7 @@ script('passman', 'app/services/settingsservice');
script('passman', 'app/services/fileservice');
script('passman', 'app/services/encryptservice');
script('passman', 'app/services/tagservice');
script('passman', 'app/services/notificationservice');
script('passman', 'app/directives/passwordgen');
script('passman', 'app/directives/fileselect');
script('passman', 'app/directives/progressbar');
@ -65,26 +67,38 @@ style('passman', 'app');
<div id="app" ng-app="passmanApp" ng-controller="MainCtrl">
<div id="app-navigation" ng-if="selectedVault" ng-controller="MenuCtrl">
<ul>
<li><a href="#">First level entry</a></li>
<li>
<a href="#">First level container</a>
<ul>
<li><a href="#">Second level entry</a></li>
<li><a href="#">Second level entry</a></li>
</ul>
<li class="taginput">
<a class="taginput">
<tags-input ng-model="selectedTags" replace-spaces-with-dashes="false">
<auto-complete source="getTags($query)" min-length="0"></auto-complete>
</tags-input>
</a>
</li>
<li ng-repeat="tag in available_tags" ng-if="selectedTags.indexOf(tag) == -1">
<a ng-click="tagClicked(tag)">{{tag.text}}</a>
</li>
<li data-id="trashbin" class="nav-trashbin">
<a ng-click="toggleDeleteTime()"
ng-class="{'active': delete_time > 0}">
<i href="#" class="fa fa-trash"></i>
Deleted credentials
</a>
</li>
</ul>
<div id="app-settings" ng-init="settingsShown = false;">
<div id="app-settings-header">
<button class="settings-button"
ng-click="settingsShown = !settingsShown"
>Settings</button>
>Settings
</button>
</div>
<div id="app-settings-content" ng-show="settingsShown">
<!-- Your settings in here -->
<div class="settings-container">
<div><span class="link">Settings</span></div>
<div><span class="link" ng-click="logout()">Logout</span></div>
<div><span class="link" ng-click="logout()">Logout</span>
</div>
</div>
</div>
</div>

View file

@ -22,7 +22,7 @@
<a href="#" editable-text="file.filename">{{ file.filename || "empty" }}</a>
</td>
<td>
{{file.created}}
{{file.created * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
</td>
<td>{{file.size | bytes}}</td>
<td class="field_actions">

View file

@ -29,12 +29,19 @@
</li>
</ul>
</div>
<input type="text" ng-model="itemFilter.label">
<span class="title" ng-if="delete_time">
Showing deleted since:
<span ng-if="delete_time == 1">All time</span>
<span ng-if="delete_time > 1">{{delete_time | date:'dd-MM-yyyy @ HH:mm:ss'}}</span>
</span>
</div>
</div>
<div off-click="closeSelected()">
<table class="credential-table" ng-init="menuOpen = false;">
<tr ng-repeat="credential in credentials"
ng-if="credential.hidden == 0 && credential.delete_time == 0"
<tr ng-repeat="credential in credentials | filter:itemFilter | tagFilter:selectedtags"
ng-if="credential.hidden == 0 && showCredentialRow(credential)"
ng-click="selectCredential(credential)"
ng-class="{'selected': selectedCredential.credential_id == credential.credential_id}">
<td>
@ -97,6 +104,15 @@
secret="'true'"></span>
</td>
</tr>
<tr ng-show="selectedCredential.otp.secret">
<td>
OTP
</td>
<td>
<span otp-generator
secret="selectedCredential.otp.secret"></span>
</td>
</tr>
<tr ng-show="selectedCredential.email">
<td>
E-mail
@ -151,15 +167,24 @@
{{selectedCredential.created * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
</td>
</tr>
</table>
<div class="tags">
<span class="tag" ng-repeat="tag in selectedCredential.tags">{{tag.text}}</span>
</div>
<div ng-show="selectedCredential">
<span class="button" ng-click="editCredential(selectedCredential)">
<span class="button" ng-click="editCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0" >
<span class="fa fa-edit"></span> Edit
</span>
<span class="button">
<span class="fa fa-trash"></span> Delete
<span class="button" ng-click="deleteCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0" >
<span class="fa fa-trash" ></span> Delete
</span>
<span class="button">
<span class="button" ng-if="selectedCredential.delete_time > 0" ng-click="recoverCredential(selectedCredential)">
<span class="fa fa-recycle" ></span> Recover
</span>
<span class="button" ng-if="selectedCredential.delete_time == 0" >
<span class="fa fa-share"></span> Share
</span>
</div>