diff options
author | brantje <brantje@gmail.com> | 2016-10-01 18:21:24 +0300 |
---|---|---|
committer | brantje <brantje@gmail.com> | 2016-10-01 18:21:24 +0300 |
commit | 64113510686357efe5bb1a88e15e121a02912ed0 (patch) | |
tree | 1dba67d503b22ca099de989b2ece4dc9e1eb69bf | |
parent | c4da0742dfd579cd7cc6a2713e7038426f9aa940 (diff) |
Add bookmarklet
-rw-r--r-- | Gruntfile.js | 7 | ||||
-rw-r--r-- | appinfo/routes.php | 1 | ||||
-rw-r--r-- | controller/pagecontroller.php | 8 | ||||
-rw-r--r-- | css/app.css | 2 | ||||
-rw-r--r-- | css/bookmarklet.css | 35 | ||||
-rw-r--r-- | css/bookmarklet.css.map | 7 | ||||
-rw-r--r-- | js/app/app.js | 32 | ||||
-rw-r--r-- | js/app/controllers/bookmarklet.js | 360 | ||||
-rw-r--r-- | js/app/controllers/settings.js | 7 | ||||
-rw-r--r-- | js/templates.js | 4 | ||||
-rw-r--r-- | sass/bookmarklet.scss | 41 | ||||
-rw-r--r-- | sass/partials/tabs.scss | 2 | ||||
-rw-r--r-- | templates/bookmarklet.php | 101 | ||||
-rw-r--r-- | templates/views/partials/forms/edit_credential/password.html | 2 | ||||
-rw-r--r-- | templates/views/partials/forms/settings/general_settings.html | 23 |
15 files changed, 604 insertions, 28 deletions
diff --git a/Gruntfile.js b/Gruntfile.js index 1ed5cbc1..cd58cf62 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -35,6 +35,13 @@ module.exports = function (grunt) { src: ["**/app.scss"], dest: "css", ext: ".css" + }, + { + expand: true, + cwd: "sass", + src: ["**/bookmarklet.scss"], + dest: "css", + ext: ".css" } ] } diff --git a/appinfo/routes.php b/appinfo/routes.php index e99b9d01..f9382742 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -20,6 +20,7 @@ return [ 'routes' => [ ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], + ['name' => 'page#bookmarklet', 'url' => '/bookmarklet', 'verb' => 'GET'], //Vault ['name' => 'vault#listVaults', 'url' => '/api/v2/vaults', 'verb' => 'GET'], diff --git a/controller/pagecontroller.php b/controller/pagecontroller.php index fd0c401d..1520cd02 100644 --- a/controller/pagecontroller.php +++ b/controller/pagecontroller.php @@ -42,5 +42,13 @@ class PageController extends Controller { } + /** + * @NoAdminRequired + * @NoCSRFRequired + */ + public function bookmarklet($url='',$title='') { + $params = array('url' => $url, 'label' => $title); + return new TemplateResponse('passman', 'bookmarklet', $params); + } }
\ No newline at end of file diff --git a/css/app.css b/css/app.css index c4eb0412..94d8af04 100644 --- a/css/app.css +++ b/css/app.css @@ -33,7 +33,7 @@ border-bottom-width: 0; margin: 0; padding: 10px 10px 10px 10px; - color: #696969; + color: #e0dddd; cursor: pointer; border-right: 1px solid #eee; -webkit-transition: background-color 250ms linear; diff --git a/css/bookmarklet.css b/css/bookmarklet.css new file mode 100644 index 00000000..89e245d2 --- /dev/null +++ b/css/bookmarklet.css @@ -0,0 +1,35 @@ +header, nav { + display: none; } + +#content-wrapper { + padding-top: 0; } + +#app-content-wrapper { + min-height: inherit !important; } + +.warning_bar .fa-times { + margin-right: 20px; } + +.tab_container { + padding-top: 10px; + margin-bottom: 20px; } + .tab_container div { + margin-bottom: 5px; + overflow: hidden; } + +.vault_wrapper { + margin-top: 70px; } + +.active_vault { + float: right; + text-align: right; + padding-right: 5px; + font-size: 10px; } + +.tab_header { + margin: 0; } + +.angularjs-datetime-picker { + z-index: 9999; } + +/*# sourceMappingURL=bookmarklet.css.map */ diff --git a/css/bookmarklet.css.map b/css/bookmarklet.css.map new file mode 100644 index 00000000..029063ad --- /dev/null +++ b/css/bookmarklet.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAAA,WAAW;EACT,OAAO,EAAE,IAAI;;AAKf,gBAAgB;EACd,WAAW,EAAE,CAAC;;AAIhB,oBAAoB;EAClB,UAAU,EAAE,kBAAkB;;AAGhC,sBAAuB;EACtB,YAAY,EAAE,IAAI;;AAEnB,cAAc;EACZ,WAAW,EAAE,IAAI;EAKjB,aAAa,EAAE,IAAI;EAJnB,kBAAG;IACD,aAAa,EAAE,GAAG;IAClB,QAAQ,EAAE,MAAM;;AAIpB,cAAc;EACZ,UAAU,EAAE,IAAI;;AAElB,aAAa;EACX,KAAK,EAAE,KAAK;EACZ,UAAU,EAAE,KAAK;EACjB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,IAAI;;AAEjB,WAAW;EACT,MAAM,EAAE,CAAC;;AAEX,0BAA0B;EACxB,OAAO,EAAE,IAAI", +"sources": ["../sass/bookmarklet.scss"], +"names": [], +"file": "bookmarklet.css" +} diff --git a/js/app/app.js b/js/app/app.js index bd9ef8b6..8e677a9e 100644 --- a/js/app/app.js +++ b/js/app/app.js @@ -94,23 +94,25 @@ jQuery(document).ready(function () { if($('#controls').length) { var controlsWidth; // if there is a scrollbar … - if($('#app-content').get(0).scrollHeight > $('#app-content').height()) { - if($(window).width() > 768) { - controlsWidth = $('#content').width() - $('#app-navigation').width() - OC.Util.getScrollBarWidth(); - if (!$('#app-sidebar').hasClass('hidden') && !$('#app-sidebar').hasClass('disappear')) { - controlsWidth -= $('#app-sidebar').width(); + if($('#app-content').get(0)) { + if ($('#app-content').get(0).scrollHeight > $('#app-content').height()) { + if ($(window).width() > 768) { + controlsWidth = $('#content').width() - $('#app-navigation').width() - OC.Util.getScrollBarWidth(); + if (!$('#app-sidebar').hasClass('hidden') && !$('#app-sidebar').hasClass('disappear')) { + controlsWidth -= $('#app-sidebar').width(); + } + } else { + controlsWidth = $('#content').width() - OC.Util.getScrollBarWidth(); } - } else { - controlsWidth = $('#content').width() - OC.Util.getScrollBarWidth(); - } - } else { // if there is none - if($(window).width() > 768) { - controlsWidth = $('#content').width() - $('#app-navigation').width(); - if (!$('#app-sidebar').hasClass('hidden') && !$('#app-sidebar').hasClass('disappear')) { - //controlsWidth -= $('#app-sidebar').width(); + } else { // if there is none + if ($(window).width() > 768) { + controlsWidth = $('#content').width() - $('#app-navigation').width(); + if (!$('#app-sidebar').hasClass('hidden') && !$('#app-sidebar').hasClass('disappear')) { + //controlsWidth -= $('#app-sidebar').width(); + } + } else { + controlsWidth = $('#content').width(); } - } else { - controlsWidth = $('#content').width(); } } if(r){ diff --git a/js/app/controllers/bookmarklet.js b/js/app/controllers/bookmarklet.js new file mode 100644 index 00000000..780bd9ae --- /dev/null +++ b/js/app/controllers/bookmarklet.js @@ -0,0 +1,360 @@ +'use strict'; + +/** + * @ngdoc function + * @name passmanApp.controller:MainCtrl + * @description + * # MainCtrl + * Controller of the passmanApp + */ +angular.module('passmanApp') + .controller('BookmarkletCtrl', ['$scope', '$rootScope', '$location', 'VaultService', 'CredentialService', 'SettingsService', 'NotificationService', 'EncryptService', 'TagService', 'FileService', + function ($scope, $rootScope, $location, VaultService, CredentialService, SettingsService, NotificationService, EncryptService, TagService, FileService) { + $scope.active_vault = false; + + $scope.http_warning_hidden = true; + if ($location.$$protocol === 'http') { + $scope.using_http = true; + //$scope.http_warning_hidden = false; + + } + + $scope.logout = function () { + $scope.active_vault = false; + }; + if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) { + var _vault = angular.copy(SettingsService.getSetting('defaultVault')); + VaultService.getVault(_vault).then(function (vault) { + vault.vaultKey = angular.copy(SettingsService.getSetting('defaultVaultPass')); + VaultService.setActiveVault(vault); + $scope.active_vault = vault; + + $scope.pwSettings = VaultService.getVaultSetting('pwSettings', + { + 'length': 12, + 'useUppercase': true, + 'useLowercase': true, + 'useDigits': true, + 'useSpecialChars': true, + 'minimumDigitCount': 3, + 'avoidAmbiguousCharacters': false, + 'requireEveryCharType': true, + 'generateOnCreate': true + }) + }) + } + /** + * Vault selection stuff + */ + VaultService.getVaults().then(function (vaults) { + $scope.vaults = vaults; + + }); + $scope.default_vault = false; + $scope.remember_vault_password = false; + $scope.list_selected_vault = false; + + + $scope.toggleDefaultVault = function () { + $scope.default_vault = !$scope.default_vault; + if ($scope.default_vault == true) { + SettingsService.setSetting('defaultVault', $scope.list_selected_vault); + } else { + SettingsService.setSetting('defaultVault', null); + } + }; + + $scope.toggleRememberPassword = function () { + $scope.remember_vault_password = !$scope.remember_vault_password; + if ($scope.remember_vault_password) { + SettingsService.setSetting('defaultVault', $scope.list_selected_vault); + $scope.default_vault = true; + } + if ($scope.remember_vault_password != true) { + SettingsService.setSetting('defaultVault', null); + } + }; + + $scope.clearState = function () { + $scope.list_selected_vault = false; + $scope.creating_vault = false; + $scope.error = false; + }; + + $scope.selectVault = function (vault) { + $scope.list_selected_vault = vault; + }; + $scope.sharing_keys = {}; + $scope.newVault = function () { + $scope.creating_vault = true; + var _vault = {}; + var key_size = 1024; + ShareService.generateRSAKeys(key_size).progress(function (progress) { + var p = progress > 0 ? 2 : 1; + $scope.creating_keys = 'Generating sharing keys (' + p + ' / 2)'; + $scope.$digest(); + }).then(function (kp) { + var pem = ShareService.rsaKeyPairToPEM(kp); + $scope.creating_keys = false; + $scope.sharing_keys.private_sharing_key = pem.privateKey; + $scope.sharing_keys.public_sharing_key = pem.publicKey; + $scope.$digest(); + }); + + }; + + var _loginToVault = function (vault, vault_key) { + var _vault = angular.copy(vault); + _vault.vaultKey = angular.copy(vault_key); + delete _vault.credentials; + $scope.active_vault = _vault; + + }; + + $scope.vaultDecryptionKey = ''; + $scope.loginToVault = function (vault, vault_key) { + $scope.error = false; + var _vault = angular.copy(vault); + _vault.vaultKey = angular.copy(vault_key); + + VaultService.setActiveVault(_vault); + try { + var c = EncryptService.decryptString(vault.challenge_password); + if ($scope.remember_vault_password) { + SettingsService.setSetting('defaultVaultPass', vault_key); + } + _loginToVault(vault, vault_key); + + } catch (e) { + $scope.error = 'Incorrect vault password!' + } + + }; + + + $scope.createVault = function (vault_name, vault_key, vault_key2) { + if (vault_key != vault_key2) { + $scope.error = 'Passwords do not match'; + return; + } + VaultService.createVault(vault_name).then(function (vault) { + $scope.vaults.push(vault); + var _vault = angular.copy(vault); + _vault.vaultKey = angular.copy(vault_key); + VaultService.setActiveVault(_vault); + var test_credential = CredentialService.newCredential(); + test_credential.label = 'Test key for vault ' + vault_name; + test_credential.hidden = true; + test_credential.vault_id = vault.vault_id; + test_credential.password = 'lorum ipsum'; + CredentialService.createCredential(test_credential).then(function (result) { + _vault.public_sharing_key = angular.copy($scope.sharing_keys.public_sharing_key); + _vault.private_sharing_key = EncryptService.encryptString(angular.copy($scope.sharing_keys.private_sharing_key)); + VaultService.updateSharingKeys(_vault).then(function (result) { + _loginToVault(vault, vault_key); + }) + }) + }); + }; + + + /** + * End vault selection stiff + */ + $scope.storedCredential = CredentialService.newCredential(); + + var QueryString = function () { + // This function is anonymous, is executed immediately and + // the return value is assigned to QueryString! + var query_string = {}; + var query = window.location.search.substring(1); + var vars = query.split("&"); + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split("="); + // If first entry with this name + if (typeof query_string[pair[0]] === "undefined") { + query_string[pair[0]] = decodeURIComponent(pair[1]); + // If second entry with this name + } else if (typeof query_string[pair[0]] === "string") { + var arr = [query_string[pair[0]], decodeURIComponent(pair[1])]; + query_string[pair[0]] = arr; + // If third or later entry with this name + } else { + query_string[pair[0]].push(decodeURIComponent(pair[1])); + } + } + return query_string; + }(); + var query_string = QueryString; + $scope.storedCredential.label = query_string.title + $scope.storedCredential.url = query_string.url + + $scope.setHttpWarning = function (state) { + $scope.http_warning_hidden = state; + }; + + $scope.currentTab = { + title: 'General', + url: 'views/partials/forms/edit_credential/basics.html', + color: 'blue' + }; + + $scope.tabs = [{ + title: 'General', + url: 'views/partials/forms/edit_credential/basics.html', + color: 'blue' + }, { + title: 'Password', + url: 'views/partials/forms/edit_credential/password.html', + color: 'green' + }, { + title: 'Custom fields', + url: 'views/partials/forms/edit_credential/custom_fields.html', + color: 'orange' + }, { + title: 'Files', + url: 'views/partials/forms/edit_credential/files.html', + color: 'yellow' + }, { + title: 'OTP', + url: 'views/partials/forms/edit_credential/otp.html', + color: 'purple' + }]; + + + $scope.getTags = function ($query) { + return TagService.searchTag($query); + }; + + $scope.currentTab = { + title: 'General', + url: 'views/partials/forms/edit_credential/basics.html', + color: 'blue' + }; + + $scope.onClickTab = function (tab) { + $scope.currentTab = tab; + }; + + $scope.isActiveTab = function (tab) { + return tab.url == $scope.currentTab.url; + }; + + /** + * Below general edit functions + */ + + $scope.pwGenerated = function (pass) { + $scope.storedCredential.password_repeat = pass; + }; + + var _customField = { + label: '', + value: '', + secret: false + }; + $scope.new_custom_field = angular.copy(_customField); + + $scope.addCustomField = function () { + if (!$scope.new_custom_field.label) { + NotificationService.showNotification('Please fill in a label', 3000); + } + if (!$scope.new_custom_field.value) { + NotificationService.showNotification('Please fill in a value!', 3000); + } + if (!$scope.new_custom_field.label || !$scope.new_custom_field.value) { + return; + } + $scope.storedCredential.custom_fields.push(angular.copy($scope.new_custom_field)); + $scope.new_custom_field = angular.copy(_customField); + }; + + $scope.deleteCustomField = function (field) { + var idx = $scope.storedCredential.custom_fields.indexOf(field); + $scope.storedCredential.custom_fields.splice(idx, 1); + }; + + $scope.new_file = { + name: '', + data: null + }; + + $scope.deleteFile = function (file) { + var idx = $scope.storedCredential.files.indexOf(file); + FileService.deleteFile(file).then(function () { + $scope.storedCredential.files.splice(idx, 1); + }); + }; + + $scope.fileLoaded = function (file) { + var _file = { + filename: file.name, + size: file.size, + mimetype: file.type, + data: file.data + }; + FileService.uploadFile(_file).then(function (result) { + delete result.file_data; + result.filename = EncryptService.decryptString(result.filename); + $scope.storedCredential.files.push(result); + }); + + + $scope.$digest() + }; + + $scope.fileLoadError = function (error, file) { + console.log(error, file) + }; + + $scope.selected_file = ''; + $scope.fileprogress = []; + $scope.fileSelectProgress = function (progress) { + if (progress) { + $scope.fileprogress = progress; + $scope.$digest() + + } + }; + $scope.renewIntervalValue = 0; + $scope.renewIntervalModifier = '0'; + + $scope.updateInterval = function (renewIntervalValue, renewIntervalModifier) { + var value = parseInt(renewIntervalValue); + var modifier = parseInt(renewIntervalModifier); + if (value && modifier) { + $scope.storedCredential.renew_interval = value * modifier; + } + }; + + $scope.parseQR = function (QRCode) { + var re = /otpauth:\/\/(totp|hotp)\/(.*)\?(secret|issuer)=(.*)&(issuer|secret)=(.*)/, parsedQR, qrInfo; + parsedQR = (QRCode.qrData.match(re)); + if (parsedQR) + qrInfo = { + type: parsedQR[1], + label: decodeURIComponent(parsedQR[2]), + qr_uri: QRCode + }; + qrInfo[parsedQR[3]] = parsedQR[4]; + qrInfo[parsedQR[5]] = parsedQR[6]; + $scope.storedCredential.otp = qrInfo; + $scope.$digest() + }; + + + $scope.saveCredential = function () { + //@TODO validation + delete $scope.storedCredential.password_repeat; + if (!$scope.storedCredential.credential_id) { + $scope.storedCredential.vault_id = $scope.active_vault.vault_id; + + CredentialService.createCredential($scope.storedCredential).then(function (result) { + NotificationService.showNotification('Credential created!', 5000) + }) + } + }; + + } + ]); + diff --git a/js/app/controllers/settings.js b/js/app/controllers/settings.js index 5ceeff83..519e6b40 100644 --- a/js/app/controllers/settings.js +++ b/js/app/controllers/settings.js @@ -8,8 +8,8 @@ * Controller of the passmanApp */ angular.module('passmanApp') - .controller('SettingsCtrl', ['$scope', '$rootScope', 'SettingsService', 'VaultService', 'CredentialService', '$location', '$routeParams', '$http', 'EncryptService','NotificationService', - function ($scope, $rootScope, SettingsService, VaultService, CredentialService, $location, $routeParams, $http, EncryptService, NotificationService) { + .controller('SettingsCtrl', ['$scope', '$rootScope', 'SettingsService', 'VaultService', 'CredentialService', '$location', '$routeParams', '$http', 'EncryptService','NotificationService','$sce', + function ($scope, $rootScope, SettingsService, VaultService, CredentialService, $location, $routeParams, $http, EncryptService, NotificationService, $sce) { $scope.vault_settings = {}; $scope.new_vault_name = ''; $scope.active_vault = VaultService.getActiveVault(); @@ -41,6 +41,9 @@ angular.module('passmanApp') }) } } + var http = location.protocol, slashes = http.concat("//"), host = slashes.concat(window.location.hostname), complete = host + location.pathname; + $scope.bookmarklet = $sce.trustAsHtml("<a class=\"button\" href=\"javascript:(function(){var a=window,b=document,c=encodeURIComponent,e=c(document.title),d=a.open('" + complete + "bookmarklet?url='+c(b.location)+'&title='+e,'bkmk_popup','left='+((a.screenX||a.screenLeft)+10)+',top='+((a.screenY||a.screenTop)+10)+',height=750px,width=475px,resizable=0,alwaysRaised=1');a.setTimeout(function(){d.focus()},300);})();\">Save in passman</a>"); + $scope.saveVaultSettings = function () { diff --git a/js/templates.js b/js/templates.js index feb30de6..1058e9d1 100644 --- a/js/templates.js +++ b/js/templates.js @@ -39,7 +39,7 @@ angular.module('views/partials/forms/edit_credential/otp.html', []).run(['$templ angular.module('views/partials/forms/edit_credential/password.html', []).run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('views/partials/forms/edit_credential/password.html', - '<div class="row"><div class="col-xs-12 col-md-5 col-lg-5"><label>Password</label><div><password-gen ng-model="storedCredential.password" settings="pwSettings" callback="pwGenerated"></password-gen><ng-password-meter password="storedCredential.password"></ng-password-meter></div><label>Repeat password</label><div><input type="password" ng-model="storedCredential.password_repeat"></div><label>Expire date</label><div><span datetime-picker ng-model="storedCredential.expire_time" class="link" future-only ng-show="storedCredential.expire_time == 0" close-on-select="false">No expire date set</span> <span datetime-picker ng-model="storedCredential.expire_time" class="link" future-only ng-show="storedCredential.expire_time != 0" close-on-select="false">{{ storedCredential.expire_time | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</span></div><label>Renew interval</label><div><input type="number" ng-model="renewIntervalValue" min="0" ng-change="updateInterval(renewIntervalValue, renewIntervalModifier)"><select ng-model="renewIntervalModifier" ng-change="updateInterval(renewIntervalValue, renewIntervalModifier)"><option value="0">Disabled</option><option value="86400">Day(s)</option><option value="604800">Week(s)</option><option value="2592000">Month(s)</option><option value="31622400">Year(s)</option></select></div></div><div class="col-xs-12 col-md-7 col-lg-7">Password generation settings<div class="row"><div class="password_settings"><div class="col-xs-12 col-sm-5 col-lg-4"><label><span class="label">Password length</span><br><input type="number" ng-model="pwSettings.length" min="1"></label><label><span class="label">Minimum amount of digits</span><br><input type="number" ng-model="pwSettings.minimumDigitCount" min="0"></label></div><div class="col-xs-12 col-sm-6 col-lg-6"><label><input type="checkbox" ng-model="pwSettings.useUppercase"> <span class="label sm">Use uppercase letters</span></label><label><input ng-model="pwSettings.useLowercase" type="checkbox" id="lower"> <span class="label sm">Use lowercase letters</span></label><label><input ng-model="pwSettings.useDigits" type="checkbox" id="digits"> <span class="label sm">Use numbers</span></label><label><input type="checkbox" id="special" ng-model="pwSettings.useSpecialChars"> <span class="label sm">Use special characters</span></label><label><input type="checkbox" id="ambig" ng-model="pwSettings.avoidAmbiguousCharacters"> <span class="label sm">Avoid ambiguous characters</span></label><label><input type="checkbox" ng-model="pwSettings.requireEveryCharType" id="reqevery"> <span class="label sm">Require every character type</span></label></div></div></div></div></div>'); + '<div class="row"><div class="col-xs-12 col-md-5 col-lg-5"><label>Password</label><div><password-gen ng-model="storedCredential.password" settings="pwSettings" callback="pwGenerated"></password-gen><ng-password-meter password="storedCredential.password"></ng-password-meter></div><label>Repeat password</label><div><input type="password" ng-model="storedCredential.password_repeat"></div><label>Expire date</label><div><span datetime-picker ng-model="storedCredential.expire_time" class="link" future-only ng-show="storedCredential.expire_time == 0" close-on-select="false">No expire date set</span> <span datetime-picker ng-model="storedCredential.expire_time" class="link" future-only ng-show="storedCredential.expire_time != 0" close-on-select="false">{{ storedCredential.expire_time | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</span></div><label>Renew interval</label><div><input type="number" ng-model="renewIntervalValue" min="0" ng-change="updateInterval(renewIntervalValue, renewIntervalModifier)"><select ng-model="renewIntervalModifier" ng-change="updateInterval(renewIntervalValue, renewIntervalModifier)"><option value="0">Disabled</option><option value="86400">Day(s)</option><option value="604800">Week(s)</option><option value="2592000">Month(s)</option><option value="31622400">Year(s)</option></select></div></div><div class="col-xs-12 col-md-7 col-lg-7"><b>Password generation settings</b><div class="row"><div class="password_settings"><div class="col-xs-12 col-sm-5 col-lg-4"><label><span class="label">Password length</span><br><input type="number" ng-model="pwSettings.length" min="1"></label><label><span class="label">Minimum amount of digits</span><br><input type="number" ng-model="pwSettings.minimumDigitCount" min="0"></label></div><div class="col-xs-12 col-sm-6 col-lg-6"><label><input type="checkbox" ng-model="pwSettings.useUppercase"> <span class="label sm">Use uppercase letters</span></label><label><input ng-model="pwSettings.useLowercase" type="checkbox" id="lower"> <span class="label sm">Use lowercase letters</span></label><label><input ng-model="pwSettings.useDigits" type="checkbox" id="digits"> <span class="label sm">Use numbers</span></label><label><input type="checkbox" id="special" ng-model="pwSettings.useSpecialChars"> <span class="label sm">Use special characters</span></label><label><input type="checkbox" id="ambig" ng-model="pwSettings.avoidAmbiguousCharacters"> <span class="label sm">Avoid ambiguous characters</span></label><label><input type="checkbox" ng-model="pwSettings.requireEveryCharType" id="reqevery"> <span class="label sm">Require every character type</span></label></div></div></div></div></div>'); }]); angular.module('views/partials/forms/settings/export.html', []).run(['$templateCache', function($templateCache) { @@ -51,7 +51,7 @@ angular.module('views/partials/forms/settings/export.html', []).run(['$templateC angular.module('views/partials/forms/settings/general_settings.html', []).run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('views/partials/forms/settings/general_settings.html', - '<div class="row"><div class="col-xs-12 col-md-6"><h3>Rename vault</h3><label>New vault name</label><input type="text" ng-model="$parent.new_vault_name"> <button ng-click="saveVaultSettings()" tooltip="\'Not working :P\'">Change</button><h3>Change vault key</h3><label>Old vault password</label><input type="password" ng-model="oldVaultPass"><label>New vault password</label><password-gen ng-model="newVaultPass"></password-gen><ng-password-meter password="newVaultPass"></ng-password-meter><label>New vault password</label><input type="password" ng-model="newVaultPass2"> <button ng-click="changeVaultPassword(oldVaultPass,newVaultPass,newVaultPass2)" tooltip="\'Not working :P\'">Change</button></div><div class="col-xs-12 col-md-6"><h3>About passman</h3><p>Version: <b>{{passman_version}}</b><br>Bla bla about passman, changelog.<br><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" target="_blank" class="link">Donate to support development</a></p></div></div>'); + '<div class="row"><div class="col-xs-12 col-md-6"><h3>Rename vault</h3><label>New vault name</label><input type="text" ng-model="$parent.new_vault_name"> <button ng-click="saveVaultSettings()" tooltip="\'Not working :P\'">Change</button><h3>Change vault key</h3><label>Old vault password</label><input type="password" ng-model="oldVaultPass"><label>New vault password</label><password-gen ng-model="newVaultPass"></password-gen><ng-password-meter password="newVaultPass"></ng-password-meter><label>New vault password</label><input type="password" ng-model="newVaultPass2"> <button ng-click="changeVaultPassword(oldVaultPass,newVaultPass,newVaultPass2)" tooltip="\'Not working :P\'">Change</button></div><div class="col-xs-12 col-md-6"><h3>About passman</h3><p>Version: <b>{{passman_version}}</b><br>Bla bla about passman, changelog.<br><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" target="_blank" class="link">Donate to support development</a><br></p><h3>Bookmarklet</h3><div><p>Save your passwords with 1 click!<br>Drag below button to your bookmark toolbar.<br></p></div><div><p ng-bind-html="bookmarklet" style="margin-top: 5px"></p></div></div></div>'); }]); angular.module('views/partials/forms/settings/import.html', []).run(['$templateCache', function($templateCache) { diff --git a/sass/bookmarklet.scss b/sass/bookmarklet.scss new file mode 100644 index 00000000..65b25237 --- /dev/null +++ b/sass/bookmarklet.scss @@ -0,0 +1,41 @@ +header, nav{ + display: none; +} +#content{ + +} +#content-wrapper{ + padding-top: 0; + +} + +#app-content-wrapper{ + min-height: inherit !important; +} + +.warning_bar .fa-times { + margin-right: 20px; +} +.tab_container{ + padding-top: 10px; + div{ + margin-bottom: 5px; + overflow: hidden; + } + margin-bottom: 20px; +} +.vault_wrapper{ + margin-top: 70px; +} +.active_vault{ + float: right; + text-align: right; + padding-right: 5px; + font-size: 10px; +} +.tab_header{ + margin: 0; +} +.angularjs-datetime-picker{ + z-index: 9999; +}
\ No newline at end of file diff --git a/sass/partials/tabs.scss b/sass/partials/tabs.scss index c04b87db..1286e2f5 100644 --- a/sass/partials/tabs.scss +++ b/sass/partials/tabs.scss @@ -11,7 +11,7 @@ border-bottom-width: 0; margin: 0; padding: 10px 10px 10px 10px; - color: #696969; + color: #e0dddd; cursor: pointer; border-right: 1px solid #eee; -webkit-transition: background-color 250ms linear; diff --git a/templates/bookmarklet.php b/templates/bookmarklet.php new file mode 100644 index 00000000..6bae81b8 --- /dev/null +++ b/templates/bookmarklet.php @@ -0,0 +1,101 @@ +<?php +/* + * Javascripts + */ +script('passman', 'vendor/angular/angular.min'); +script('passman', 'vendor/angular-animate/angular-animate.min'); +script('passman', 'vendor/angular-cookies/angular-cookies.min'); +script('passman', 'vendor/angular-resource/angular-resource.min'); +script('passman', 'vendor/angular-route/angular-route.min'); +script('passman', 'vendor/angular-sanitize/angular-sanitize.min'); +script('passman', 'vendor/angular-touch/angular-touch.min'); +script('passman', 'vendor/angular-local-storage/angular-local-storage.min'); +script('passman', 'vendor/angular-off-click/angular-off-click.min'); +script('passman', 'vendor/angularjs-datetime-picker/angularjs-datetime-picker.min'); +script('passman', 'vendor/ng-password-meter/ng-password-meter'); +script('passman', 'vendor/sjcl/sjcl'); +script('passman', 'vendor/zxcvbn/zxcvbn'); +script('passman', 'vendor/ng-clipboard/clipboard.min'); +script('passman', 'vendor/ng-clipboard/ngclipboard'); +script('passman', 'vendor/ng-tags-input/ng-tags-input.min'); +script('passman', 'vendor/angular-xeditable/xeditable.min'); +script('passman', 'vendor/sha/sha'); +script('passman', 'vendor/llqrcode/llqrcode'); +script('passman', 'vendor/forge.0.6.9.min'); +script('passman', 'lib/promise'); +script('passman', 'lib/crypto_wrap'); + + +script('passman', 'app/app'); +script('passman', 'templates'); +script('passman', 'app/controllers/edit_credential'); +script('passman', 'app/controllers/bookmarklet'); +script('passman', 'app/filters/range'); +script('passman', 'app/filters/propsfilter'); +script('passman', 'app/filters/byte'); +script('passman', 'app/services/vaultservice'); +script('passman', 'app/services/credentialservice'); +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/services/shareservice'); +script('passman', 'app/directives/passwordgen'); +script('passman', 'app/directives/fileselect'); +script('passman', 'app/directives/progressbar'); +script('passman', 'app/directives/otp'); +script('passman', 'app/directives/qrreader'); +script('passman', 'app/directives/tooltip'); +script('passman', 'app/directives/use-theme'); +script('passman', 'app/directives/credentialfield'); +script('passman', 'app/directives/ngenter'); +script('passman', 'app/directives/autoscroll'); +script('passman', 'app/directives/clickselect'); +script('passman', 'app/directives/colorfromstring'); +/* + * Styles + */ +style('passman', 'vendor/ng-password-meter/ng-password-meter'); +style('passman', 'vendor/bootstrap/bootstrap.min'); +style('passman', 'vendor/bootstrap/bootstrap-theme.min'); +style('passman', 'vendor/font-awesome/font-awesome.min'); +style('passman', 'vendor/angular-xeditable/xeditable.min'); +style('passman', 'vendor/ng-tags-input/ng-tags-input.min'); +style('passman', 'vendor/angularjs-datetime-picker/angularjs-datetime-picker'); +style('passman', 'app'); +style('passman', 'bookmarklet'); + +?> + +<div id="app" ng-app="passmanApp" ng-controller="BookmarkletCtrl"> + <div class="warning_bar" ng-if="using_http && http_warning_hidden == false"> + Warning! Adding credentials over http can be insecure! + <i class="fa fa-times fa-2x" alt="Close" + ng-click="setHttpWarning(true);"></i> + </div> + <div id="app-content"> + <div id="app-content-wrapper" ng-if="active_vault === false"> + <div ng-include="'views/vaults.html'"></div> + </div> + <div id="app-content-wrapper" ng-if="active_vault !== false"> + <div class="active_vault"> + Logged in to {{active_vault.name}}<br /> + <span class="link" ng-click="logout()">Change vault</span> + </div> + <ul class="tab_header"> + <li ng-repeat="tab in tabs track by $index" class="tab" + ng-class="{active:isActiveTab(tab)}" + ng-click="onClickTab(tab)" use-theme + >{{tab.title}} + </li> + </ul> + + <div class="tab_container edit_credential"> + <div ng-include="currentTab.url"></div> + <button ng-click="saveCredential()">Save</button> + <button ng-click="cancel()">Cancel</button> + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/templates/views/partials/forms/edit_credential/password.html b/templates/views/partials/forms/edit_credential/password.html index e9291744..b9576c37 100644 --- a/templates/views/partials/forms/edit_credential/password.html +++ b/templates/views/partials/forms/edit_credential/password.html @@ -38,7 +38,7 @@ </div> </div> <div class="col-xs-12 col-md-7 col-lg-7"> - Password generation settings + <b>Password generation settings</b> <div class="row"> <div class="password_settings"> diff --git a/templates/views/partials/forms/settings/general_settings.html b/templates/views/partials/forms/settings/general_settings.html index 5522324d..2ba51a0c 100644 --- a/templates/views/partials/forms/settings/general_settings.html +++ b/templates/views/partials/forms/settings/general_settings.html @@ -3,7 +3,9 @@ <h3>Rename vault</h3> <label>New vault name</label> <input type="text" ng-model="$parent.new_vault_name"> - <button ng-click="saveVaultSettings()" tooltip="'Not working :P'">Change</button> + <button ng-click="saveVaultSettings()" tooltip="'Not working :P'"> + Change + </button> <h3>Change vault key</h3> @@ -11,19 +13,28 @@ <input type="password" ng-model="oldVaultPass"> <label>New vault password</label> <password-gen ng-model="newVaultPass" - ></password-gen> + ></password-gen> <ng-password-meter password="newVaultPass"></ng-password-meter> <label>New vault password</label> <input type="password" ng-model="newVaultPass2"> - <button ng-click="changeVaultPassword(oldVaultPass,newVaultPass,newVaultPass2)" tooltip="'Not working :P'">Change</button> + <button ng-click="changeVaultPassword(oldVaultPass,newVaultPass,newVaultPass2)" + tooltip="'Not working :P'">Change + </button> </div> <div class="col-xs-12 col-md-6"> <h3>About passman</h3> <p> - Version: <b>{{passman_version}}</b><br /> + Version: <b>{{passman_version}}</b><br/> Bla bla about passman, changelog. - <br /> - <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" target="_blank" class="link">Donate to support development</a> + <br/> + <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" + target="_blank" class="link">Donate to support + development</a><br/> </p> + <h3>Bookmarklet</h3> + <div><p>Save your passwords with 1 click!<br/> Drag below button to your + bookmark toolbar.<br/></p> + </div> + <div><p ng-bind-html="bookmarklet" style="margin-top: 5px"></p></div> </div> </div>
\ No newline at end of file |