Merge remote-tracking branch 'origin/fix_layout_for_14' into feature/merges_v2.2.0

This commit is contained in:
WolFi 2018-12-16 12:36:57 +01:00
commit 5643d9c318
No known key found for this signature in database
GPG key ID: 7D15585354D072FF
51 changed files with 1190 additions and 533 deletions

View file

@ -1,7 +1,9 @@
language: php
php:
- 5.6
- 7
- 7.0
- 7.1
- 7.2
env:
global:
- CORE_BRANCH=master
@ -15,6 +17,7 @@ env:
branches:
only:
- master
- fix_layout_for_14
before_install:
@ -83,17 +86,13 @@ addons:
matrix:
include:
- php: 5.6
env: DB=sqlite;CLOUD=owncloud;SERVER_FOLDER=core
- php: 5.6
env: DB=mysql;CLOUD=owncloud;SERVER_FOLDER=core
- php: 5.6
env: DB=mysql;JSTESTS=1;
- php: 7.0
env: DB=mysql;
# - php: 7.0
# env: DB=sqlite;CLOUD=owncloud;SERVER_FOLDER=core
# - php: 7.0
# env: DB=mysql;CLOUD=owncloud;SERVER_FOLDER=core
- php: 7.0
env: DB=sqlite;CLOUD=owncloud;SERVER_FOLDER=core
- php: 7.0
env: DB=mysql;CLOUD=owncloud;SERVER_FOLDER=core
env: DB=mysql;JSTESTS=1;
allow_failures:
- env: DB=sqlite;CODECHECK=2

View file

@ -7,6 +7,12 @@ Passman is a full featured password manager.
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/749bb288c9fd4592a73056549d44a85e)](https://www.codacy.com/app/brantje/passman?utm_source=github.com&utm_medium=referral&utm_content=nextcloud/passman&utm_campaign=Badge_Coverage)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nextcloud/passman/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/nextcloud/passman/?branch=master)
## Join us!
There is a Telegram-Group:
* [Passman General](https://t.me/passman_general)
Those are mainly used to discuss all sorts of topics for Passman and it's apps!
## Contents
* [Screenshots](https://github.com/nextcloud/passman#Screenshots)
@ -16,6 +22,7 @@ Passman is a full featured password manager.
* [Password generation](https://github.com/nextcloud/passman#password-generation)
* [Storing credentials](https://github.com/nextcloud/passman#storing-credentials)
* [Support passman](https://github.com/nextcloud/passman#support-passman)
* [Development](https://github.com/nextcloud/passman#development)
* [API](https://github.com/nextcloud/passman#api)
* [Docker](https://github.com/nextcloud/passman#docker)
* [Maintainers](https://github.com/nextcloud/passman#main-developers)
@ -57,8 +64,9 @@ For more screenshots: [Click here](http://imgur.com/a/giKVt)
For a demo of this app visit [https://demo.passman.cc](https://demo.passman.cc)
## Tested on
- NextCloud 10 / 11
- ownCloud 9.1+
- Nextcloud 14
For older Versions see the [Releases Tab](https://github.com/nextcloud/passman/releases)
## External apps
@ -103,8 +111,6 @@ This time using the following routine:
### Sharing credentials.
Passman allows users to share passwords (this can be turned off by an administrator).
## API
For developers Passman offers an [api](https://github.com/nextcloud/passman/wiki/API).
@ -160,7 +166,7 @@ To run the unit tests install phpunit globally, and setup the environment variab
## Contributors
Add yours when creating a [pull request](https://help.github.com/articles/creating-a-pull-request/)!
- None
- Newhinton
## FAQ

View file

@ -19,7 +19,7 @@ Features:
- Import from various password managers (KeePass, LastPass, DashLane, ZOHO, Clipperz.is )
For an demo of this app visit [https://demo.passman.cc](https://demo.passman.cc)
]]></description>
<version>2.1.5</version>
<version>2.2.0</version>
<licence>agpl</licence>
<author homepage="https://github.com/brantje">Sander Brand</author>
<author homepage="https://github.com/animalillo">Marcos Zuriaga</author>
@ -37,13 +37,13 @@ For an demo of this app visit [https://demo.passman.cc](https://demo.passman.cc)
<screenshot small-thumbnail="https://img.passman.cc/thumbs/share_credential.png">https://img.passman.cc/share_credential.png</screenshot>
<screenshot small-thumbnail="https://img.passman.cc/thumbs/password_audit.png">https://img.passman.cc/password_audit.png</screenshot>
<dependencies>
<php min-version="5.6"/>
<php min-version="7.0"/>
<database>sqlite</database>
<database>pgsql</database>
<database min-version="5.5">mysql</database>
<lib>openssl</lib>
<owncloud min-version="9" max-version="11" />
<nextcloud min-version="9" max-version="14" />
<nextcloud min-version="14" />
<owncloud min-version="14" />
</dependencies>
<background-jobs>

43
bower.json Normal file
View file

@ -0,0 +1,43 @@
{
"name": "Passman",
"description": "Passman is a fully featured password manager",
"main": "",
"authors": [
"Sander Brand <brantje(AT)gmail.com>"
],
"license": "AGPLv3",
"homepage": "passman.cc",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"core/vendor",
"test",
"tests"
],
"dependencies": {
"angular": "1.5.8",
"angular-animate": "1.5.8",
"angular-cookies": "1.5.8",
"angular-local-storage": "0.4.0",
"angular-mocks": "1.5.8",
"angular-off-click": "1.0.6",
"angular-resource": "1.5.8",
"angular-route": "1.5.8",
"angular-sanitize": "1.5.8",
"angular-touch": "1.5.8",
"angular-translate": "2.9.0",
"angular-xeditable": "0.3.0",
"angular-datetime-picker": "",
"ng-clipboard": "1.5.10",
"ng-password-meter": "0.4.0",
"ng-tags-input": "3.1.1",
"papa-parse": "4.1.2",
"llqrcode": "0.0.2",
"sha": " 2.0.1",
"sjcl": " 1.0.8",
"ui-sortable": "0.19.0",
"zxcvbn": "4.4.2"
}
}

View file

@ -347,6 +347,16 @@ class TranslationController extends ApiController {
'decline' => $this->trans->t('Decline'),
'session.time.left' => $this->trans->t('You have {{session_time}} left before logout.'),
'vault.locked' => $this->trans->t('Your vault has been locked for {{time}} because of {{tries}} failed attempts!'),
'vault.hint.hello' => $this->trans->t('Hello there!'),
'vault.hint.hello.add' => $this->trans->t('It does not seem that you have any passwords. Do you want to add one?'),
'vault.hint.list.nogood' => $this->trans->t('You don\'t have good credentials'),
'vault.hint.list.nomedium' => $this->trans->t('You don\'t have medium credentials'),
'vault.hint.list.nobad' => $this->trans->t('You don\'t have bad credentials'),
'vault.hint.list.noexpired' => $this->trans->t('You don\'t have expired credentials'),
'vault.hint.list.nodeleted' => $this->trans->t('You don\'t have deleted credentials'),
'vault.hint.list.notags' => $this->trans->t('There are no credentials with your selected tags'),
'vault.hint.list.nosearch' => $this->trans->t('There are no credentials matching'),
// templates/views/vaults.html
'last.access' => $this->trans->t('Last accessed'),
@ -391,6 +401,16 @@ class TranslationController extends ApiController {
'deleted.credentials' => $this->trans->t('Deleted credentials'),
'logout' => $this->trans->t('Logout'),
'donate' => $this->trans->t('Donate'),
'navigation.show.all' => $this->trans->t('Show All'),
'navigation.tags' => $this->trans->t('Tags'),
'navigation.tags.search' => $this->trans->t('Search Tags'),
'navigation.strength.good' => $this->trans->t('Good Strength'),
'navigation.strength.medium' => $this->trans->t('Medium Strength'),
'navigation.strength.bad' => $this->trans->t('Bad Strength'),
'navigation.expired' => $this->trans->t('Expired'),
'navigation.advanced.filter' => $this->trans->t('Filter Tags'),
'navigation.advanced.checkbox' => $this->trans->t('Simple Navigation'),
// templates/public_share.php
'share.page.text' => $this->trans->t('Someone has shared a credential with you.'),

View file

@ -4,10 +4,5 @@
width: 350px; }
#passwordSharingSettings #requests-table {
width: 100%; }
#passwordSharingSettings .link {
color: #0066ff !important;
cursor: pointer; }
#passwordSharingSettings .link:hover {
text-decoration: underline; }
/*# sourceMappingURL=admin.css.map */

View file

@ -1,6 +1,6 @@
{
"version": 3,
"mappings": "AAGM,wCAAE;EACA,OAAO,EAAE,GAAG;AAGhB,kDAAkB;EAChB,KAAK,EAAE,KAAK;AAGhB,wCAAe;EACb,KAAK,EAAE,IAAI;AAIb,8BAAK;EACH,KAAK,EAAE,kBAA2B;EAClC,MAAM,EAAE,OAAO;AAEjB,oCAAW;EACT,eAAe,EAAE,SAAS",
"mappings": "AAGM,wCAAE;EACA,OAAO,EAAE,GAAG;AAGhB,kDAAkB;EAChB,KAAK,EAAE,KAAK;AAGhB,wCAAe;EACb,KAAK,EAAE,IAAI",
"sources": ["../sass/admin.scss"],
"names": [],
"file": "admin.css"

View file

@ -98,13 +98,6 @@
background: #d83a02;
color: #fff; }
.link {
color: #0066ff !important;
cursor: pointer; }
.link:hover {
text-decoration: underline; }
/**
* Nextcloud - passman
*
@ -126,67 +119,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Nextcloud - passman
*
* @copyright Copyright (c) 2016, Sander Brand (brantje@gmail.com)
* @copyright Copyright (c) 2016, Marcos Zuriaga Miguel (wolfi@wolfi.es)
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
.tab_header {
margin: 44px 0 0;
list-style: none;
padding: 0; }
.tab_header li.tab:first-child {
margin-left: 0; }
.tab_header li.tab {
/*@include border-top-radius(2px);*/
float: left;
border-bottom-width: 0;
margin: 0;
padding: 10px 10px 10px 10px;
cursor: pointer;
border-right: 1px solid #eee;
-webkit-transition: background-color 250ms linear;
-moz-transition: background-color 250ms linear;
-o-transition: background-color 250ms linear;
-ms-transition: background-color 250ms linear;
transition: background-color 250ms linear; }
.tab_header li.tab .indicator {
display: none; }
.tab_header li.active {
color: #fff;
position: relative; }
.tab_header li.active .indicator {
display: inline-block;
position: absolute;
height: 7px;
left: 0;
right: 0;
bottom: -1px; }
.tab_container {
border: 1px solid;
border-color: #eee;
border-top-color: #0082c9;
border-bottom: 0;
clear: both;
padding: 0 1em; }
/**
* Nextcloud - passman
*
@ -231,7 +163,8 @@
.pw-gen .generate_pw {
float: left;
margin-top: 3px;
margin-left: -3px; }
margin-left: -3px;
padding-bottom: 1px; }
.pw-gen .generate_pw .cell {
padding: 5px;
display: inline-block;
@ -275,7 +208,7 @@
padding: 12px;
font-weight: bold;
text-align: center;
z-index: 800;
z-index: 1800;
background-color: red;
color: white; }
.warning_bar .fa-times {
@ -284,9 +217,8 @@
cursor: pointer; }
.vault_wrapper {
margin: 0 auto;
margin-top: 20px;
width: 100%;
margin: 0 auto auto auto;
transform: translate(-150px);
max-width: 420px;
-webkit-border-radius: 5px;
border-radius: 5px;
@ -360,21 +292,45 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#content {
padding-top: 47px !important;
height: 100%;
width: 100%; }
.icon-image {
width: 16px; }
#app-sidebar {
height: auto; }
#app-sidebar .sidebar {
display: inline-block; }
#app-sidebar .sidebar .sidebar-icon {
margin-right: 15px; }
#app-sidebar .sidebar .sidebar-icon .icon-image {
width: 44px; }
#app-sidebar .sidebar .sidebar-icon i {
width: 44px; }
#app-sidebar .sidebar .sidebar-label {
float: right;
line-height: 44px; }
#app-content {
margin-left: 300px;
width: calc(100vw - 300px);
overflow-x: hidden; }
#app-content #app-content-wrapper {
min-height: 95%; }
min-height: 95%;
display: flex;
height: calc(100vh - 49px); }
#app-content #app-content-wrapper #passman-controls {
text-align: center;
border-bottom: 1px solid #c9c9c9; }
#app-content #app-content-wrapper #passman-controls.sidebar-shown {
padding-right: 27% !important; }
@media screen and (max-width: 765px) {
#app-content #app-content-wrapper #passman-controls.sidebar-shown .title {
display: none; } }
@media screen and (min-width: 769px) and (max-width: 1120px) {
#app-content #app-content-wrapper #passman-controls.sidebar-shown .title {
display: none; } }
@media screen and (max-width: 765px) {
#app-content #app-content-wrapper #passman-controls.sidebar-shown .title {
display: none; } }
@media screen and (min-width: 769px) and (max-width: 1120px) {
#app-content #app-content-wrapper #passman-controls.sidebar-shown .title {
display: none; } }
#app-content #app-content-wrapper .title {
text-align: center;
display: inline-block;
@ -386,6 +342,8 @@
@media screen and (min-width: 769px) and (max-width: 820px) {
#app-content #app-content-wrapper .title {
display: none; } }
#app-content #app-content-wrapper .breadcrumb {
float: left; }
#app-content #app-content-wrapper .actions.creatable {
float: left;
overflow: hidden; }
@ -437,7 +395,9 @@
display: inline-block;
padding: 7px; }
#app-content #app-content-wrapper .searchboxContainer {
display: inline-block;
/*display: inline-block;*/
visibility: hidden;
display: none;
margin-right: 14px;
float: right; }
#app-content #app-content-wrapper .searchboxContainer .searchbox {
@ -466,8 +426,7 @@
border-bottom-left-radius: 3px;
background-clip: padding-box; }
#app-content #app-content-wrapper .credential-table {
width: 100%;
margin-top: 44px; }
width: 100%; }
#app-content #app-content-wrapper .credential-table tr:hover {
background-color: whitesmoke; }
#app-content #app-content-wrapper .credential-table tr.selected {
@ -524,7 +483,8 @@
#app-content #app-content-wrapper .tags .tag:last-child {
margin-right: 8px; }
#app-content #app-content-wrapper .grid-view {
margin-top: 44px;
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap; }
#app-content #app-content-wrapper .grid-view .credential {
@ -542,20 +502,21 @@
flex-direction: column;
width: 100%;
cursor: pointer;
font-size: 1.75em;
text-align: center; }
font-size: 1.75em; }
#app-content #app-content-wrapper .grid-view .credential .credential_content .label {
padding-top: 0.5em;
padding-left: 1em;
padding-right: 1em;
line-height: 1.3em;
word-wrap: break-word; }
word-wrap: break-word;
float: right; }
#app-content #app-content-wrapper .grid-view .credential .credential_content .tags {
margin-bottom: 0.5em; }
margin: 0 0 auto;
text-align: right; }
#app-content #app-content-wrapper .grid-view .credential .credential_content .tags .tag {
color: #000 !important;
margin-top: 5px;
display: inline-block; }
display: inline-block;
left: 0; }
@media all and (min-width: 40em) {
#app-content #app-content-wrapper .grid-view .credential {
width: 40%; } }
@ -648,7 +609,16 @@
vertical-align: middle; }
#app-content #app-content-wrapper .edit_credential .otpText {
padding-right: 10px; }
#app-content #app-content-wrapper .main_list {
flex: 1;
float: left;
height: auto;
overflow: auto;
width: 100%; }
#app-content #app-content-wrapper .main_list .share {
overflow: hidden; }
#app-content #app-content-wrapper .app_sidebar {
float: right;
padding: 10px;
overflow-y: auto; }
#app-content #app-content-wrapper .app_sidebar h2 {
@ -762,7 +732,8 @@
/* "hand" cursor */ }
.btn-danger {
color: #fff; }
color: #000000;
background-color: #ff0000; }
.icon-label {
overflow: hidden; }
@ -787,15 +758,12 @@
.icon-label .icon-picker {
float: left;
margin-top: 3px;
margin-left: -3px;
-webkit-border-bottom-left-radius: 3px;
border-bottom-left-radius: 3px;
-webkit-border-top-left-radius: 3px;
border-top-left-radius: 3px;
background-clip: padding-box; }
padding-top: 7px; }
.icon-label .icon-picker .cell {
margin-top: 0px;
margin-left: -0px;
padding: 7px 12px 2px 12px;
display: inline-block;
display: inline;
font-size: 14px;
border: 1px solid #ddd;
background-color: #eaeaea;
@ -805,8 +773,6 @@
-webkit-border-top-left-radius: 6px;
border-top-left-radius: 6px;
background-clip: padding-box; }
.icon-label .icon-picker .cell img {
height: 16px; }
.icon-label .icon-picker .cell:hover {
color: #0066ff; }
@ -849,29 +815,38 @@
*/
.settings-container div {
padding-left: 15px; }
.settings-container button {
width: 80%;
margin-left: 15px;
margin-right: 15px; }
#app-navigation > ul {
padding-bottom: 80px; }
#app-navigation > ul > li > a {
padding-left: 12px !important;
z-index: auto; }
#app-navigation > ul > li > a {
z-index: auto; }
.nav-trashbin {
position: fixed !important;
bottom: 44px;
width: inherit !important;
border-right: 1px solid #eee; }
.nav-trashbin a {
background-color: #fff !important;
opacity: 1 !important;
z-index: 140;
padding: 0 20px; }
.nav-trashbin a.active {
border-left: 3px solid #0082c9; }
z-index: 140; }
.nav-trashbin a .fa {
margin-right: 15px; }
#taginput {
visibility: hidden;
display: none; }
#app-navigation .collapsible:hover .app-navigation-entry-bullet {
background: var(--color-primary) !important; }
#app-navigation li .app-navigation-entry-bullet-color {
background-color: var(--color-primary); }
#app-navigation li .highlight-selected {
background-color: var(--color-primary); }
#app-navigation li a.taginput {
visibility: hidden;
display: none;
opacity: 1; }
#app-navigation li a {
overflow: visible; }
@ -985,7 +960,6 @@
padding: 3px 5px; }
#app-settings-content:not(.ng-hide) {
height: 90px;
display: inherit !important;
padding: 0;
transition: height 0.15s ease-out; }
@ -1004,7 +978,8 @@
margin-right: 0 !important; }
#app-content #app-content-wrapper #passman-controls {
border-bottom: 1px solid #c9c9c9; }
border-bottom: 1px solid #c9c9c9;
margin-top: 5px; }
#passman-controls {
box-sizing: border-box;
@ -1012,6 +987,7 @@
top: 45px;
right: 0;
left: 0;
border-bottom: 1px solid #c9c9c9;
padding: 0 !important;
margin: 0;
background-color: rgba(255, 255, 255, 0.95);
@ -1027,8 +1003,8 @@
width: 100%; } }
@media only screen and (min-width: 768px) {
#app-navigation + #app-content #passman-controls {
left: 250px;
width: calc( 100% - 250px ) !important; } }
left: 300px;
width: calc( 100% - 300px ) !important; } }
#passman-controls .button, #passman-controls, #passman-controls input[type='submit'], #passman-controls input[type='text'], #passman-controls input[type='password'], #passman-controls select {
box-sizing: border-box;
display: inline-block;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -44,6 +44,8 @@
}
$scope.logout = function () {
//see vault.js:54
$rootScope.override_default_vault=true;
$scope.active_vault = false;
};
if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {

View file

@ -59,7 +59,7 @@
$scope.active_vault = vault;
$scope.active_vault.vaultKey = vaultKey;
if(!$rootScope.vaultCache){
$rootScope.vaultCache = [];
$rootScope.vaultCache = [];
}
VaultService.setActiveVault($scope.active_vault);
for (var i = 0; i < _credentials.length; i++) {
@ -325,97 +325,218 @@
fields: ['label', 'username', 'email', 'custom_fields']
};
//searchboxfix
$scope.$on('nc_searchbox', function(event, args) {
$scope.filterOptions.filterText=args;
});
$scope.filtered_credentials = [];
$scope.$watch('[selectedtags, filterOptions, delete_time, active_vault.credentials]', function () {
if (!$scope.active_vault) {
return;
}
if ($scope.active_vault.credentials) {
var credentials = angular.copy($scope.active_vault.credentials);
var filtered_credentials = $filter('credentialSearch')(credentials, $scope.filterOptions);
filtered_credentials = $filter('tagFilter')(filtered_credentials, $scope.selectedtags);
filtered_credentials = $filter('filter')(filtered_credentials, {hidden: 0});
$scope.filtered_credentials = filtered_credentials;
$scope.filterOptions.selectedtags = angular.copy($scope.selectedtags);
for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
var _credential = $scope.active_vault.credentials[i];
if (_credential.tags) {
TagService.addTags(_credential.tags);
}
$scope.filtered_credentials = [];
$scope.$watch('[selectedtags, filterOptions, delete_time, active_vault.credentials]', function () {
if (!$scope.active_vault) {
return;
}
if ($scope.active_vault.credentials) {
var credentials = angular.copy($scope.active_vault.credentials);
var filtered_credentials = $filter('credentialSearch')(credentials, $scope.filterOptions);
filtered_credentials = $filter('tagFilter')(filtered_credentials, $scope.selectedtags);
filtered_credentials = $filter('filter')(filtered_credentials, {hidden: 0});
$scope.filtered_credentials = filtered_credentials;
$scope.filterOptions.selectedtags = angular.copy($scope.selectedtags);
for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
var _credential = $scope.active_vault.credentials[i];
if (_credential.tags) {
TagService.addTags(_credential.tags);
}
}
}
}, true);
$scope.no_credentials_label=[];
$scope.no_credentials_label.all=true;
$scope.no_credentials_label.s_good=false;
$scope.no_credentials_label.s_medium=false;
$scope.no_credentials_label.s_low=false;
$scope.no_credentials_label.expired=false;
$scope.disableAllLabels = function(){
$scope.no_credentials_label.all=false;
$scope.no_credentials_label.s_good=false;
$scope.no_credentials_label.s_medium=false;
$scope.no_credentials_label.s_low=false;
$scope.no_credentials_label.expired=false;
};
//watch for special tags
$scope.$on('filterSpecial', function(event, args) {
$scope.disableAllLabels();
switch (args) {
case "strength_good":
$scope.filterStrength(3,1000);
$scope.no_credentials_label.s_good=true;
break;
case "strength_medium":
$scope.filterStrength(2,3);
$scope.no_credentials_label.s_medium=true;
break;
case "strength_low":
$scope.filterStrength(0,1);
$scope.no_credentials_label.s_low=true;
break;
case "expired":
$scope.filterExpired();
$scope.no_credentials_label.expired=true;
break;
case "all":
$scope.filterAll();
$scope.no_credentials_label.all=true;
break;
}
});
$scope.getListSizes = function(){
var l = $scope.filtered_credentials;
var deleted=0;
for (var i = 0; i < l.length; i++) {
if(l[i].delete_time>0){
deleted++;
}
}
}
}, true);
$scope.selectedtags = [];
var to;
$rootScope.$on('selected_tags_updated', function (evt, _sTags) {
var _selectedTags = [];
for (var x = 0; x < _sTags.length; x++) {
_selectedTags.push(_sTags[x].text);
}
$scope.selectedtags = _selectedTags;
$timeout.cancel(to);
if (_selectedTags.length > 0) {
to = $timeout(function () {
if ($scope.filtered_credentials) {
var _filtered_tags = [];
for (var i = 0; i < $scope.filtered_credentials.length; i++) {
var tags = $scope.filtered_credentials[i].tags_raw;
for (var x = 0; x < tags.length; x++) {
var tag = tags[x].text;
if (_filtered_tags.indexOf(tag) === -1) {
_filtered_tags.push(tag);
}
}
}
$rootScope.$emit('limit_tags_in_list', _filtered_tags);
}
}, 50);
}
});
$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;
}
var result=[];
result.listsize=l.length;
result.listsize_wout_deleted=l.length-deleted;
result.listsize_deleted=deleted;
return result;
};
$rootScope.$on('set_delete_time', function (event, time) {
$scope.delete_time = time;
});
$scope.filterAll = function(){
$scope.selectedtags=[];
$scope.filterOptions.filterText="";
var creds_filtered=[];
$scope.setDeleteTime = function (delete_time) {
$scope.delete_time = delete_time;
};
for (var i = 0; i < $scope.active_vault.credentials.length; i++) {
if($scope.active_vault.credentials[i].delete_time===0){
creds_filtered.push($scope.active_vault.credentials[i]);
}
}
$scope.selectedCredential = false;
$scope.selectCredential = function (credential) {
if(credential.description) {
credential.description_html = $sce.trustAsHtml(angular.copy(credential.description).replace("\n", '<br />'));
}
$scope.selectedCredential = angular.copy(credential);
$rootScope.$emit('app_menu', true);
};
$scope.filtered_credentials=$scope.filterHidden(creds_filtered);
};
$scope.closeSelected = function () {
$rootScope.$emit('app_menu', false);
$scope.selectedCredential = false;
};
$scope.filterStrength = function(strength_min, strength_max){
var initialCredentials=$scope.active_vault.credentials;
var postFiltered=[];
for (var i = 0; i < initialCredentials.length; i++) {
var _credential = initialCredentials[i];
var zxcvbn_result = zxcvbn(_credential.password);
$rootScope.$on('logout', function () {
if($scope.active_vault) {
$rootScope.vaultCache[$scope.active_vault.guid] = null;
}
$scope.active_vault = null;
$scope.credentials = [];
// $scope.$parent.selectedVault = false;
if(zxcvbn_result.score>=strength_min && zxcvbn_result.score<=strength_max){
postFiltered.push(initialCredentials[i]);
}
}
$scope.filtered_credentials=$scope.filterHidden(postFiltered);
};
$scope.filterExpired = function(){
var initialCredentials=$scope.active_vault.credentials;
var now = Date.now();
var postFiltered=[];
for (var i = 0; i < initialCredentials.length; i++) {
var _credential = initialCredentials[i];
if(_credential.expire_time!==0 && _credential.expire_time <= now){
postFiltered.push(initialCredentials[i]);
}
}
$scope.filtered_credentials=$scope.filterHidden(postFiltered);
};
$scope.filterHidden = function(list){
var list_without_hidden=[];
for (var i = 0; i < list.length; i++) {
if(list[i].hidden!==1){
list_without_hidden.push(list[i]);
}
}
return list_without_hidden;
};
$scope.selectedtags = [];
var to;
$rootScope.$on('selected_tags_updated', function (evt, _sTags) {
var _selectedTags = [];
for (var x = 0; x < _sTags.length; x++) {
_selectedTags.push(_sTags[x].text);
}
$scope.selectedtags = _selectedTags;
$timeout.cancel(to);
if (_selectedTags.length > 0) {
to = $timeout(function () {
if ($scope.filtered_credentials) {
var _filtered_tags = [];
for (var i = 0; i < $scope.filtered_credentials.length; i++) {
var tags = $scope.filtered_credentials[i].tags_raw;
for (var x = 0; x < tags.length; x++) {
var tag = tags[x].text;
if (_filtered_tags.indexOf(tag) === -1) {
_filtered_tags.push(tag);
}
}
}
$rootScope.$emit('limit_tags_in_list', _filtered_tags);
}
}, 50);
}
});
$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.selectedCredential = false;
$scope.selectCredential = function (credential) {
if (credential.description) {
credential.description_html = $sce.trustAsHtml(angular.copy(credential.description).replace("\n", '<br />'));
}
$scope.selectedCredential = angular.copy(credential);
$rootScope.$emit('app_menu', true);
};
$scope.closeSelected = function () {
$rootScope.$emit('app_menu', false);
$scope.selectedCredential = false;
};
$rootScope.$on('logout', function () {
if ($scope.active_vault) {
$rootScope.vaultCache[$scope.active_vault.guid] = null;
}
$scope.active_vault = null;
$scope.credentials = [];
//$scope.$parent.selectedVault = false;
});

View file

@ -32,8 +32,8 @@
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', 'TagService', 'NotificationService', 'ShareService', '$translate',
function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService, TagService, NotificationService, ShareService, $translate) {
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', 'TagService', 'NotificationService', 'ShareService', '$translate', '$rootScope',
function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService, TagService, NotificationService, ShareService, $translate, $rootScope) {
$scope.active_vault = VaultService.getActiveVault();
if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
if (!$scope.active_vault) {
@ -292,7 +292,7 @@
};
$scope.saving = false;
$scope.saveCredential = function () {
$scope.saving = true;
$scope.saving = true;
if ($scope.new_custom_field.label && $scope.new_custom_field.value) {
@ -301,8 +301,8 @@
if ($scope.storedCredential.password !== $scope.storedCredential.password_repeat){
$scope.saving = false;
NotificationService.showNotification($translate.instant('password.do.not.match'), 5000);
$scope.saving = false;
NotificationService.showNotification($translate.instant('password.do.not.match'), 5000);
return;
}
@ -313,7 +313,7 @@
if (!$scope.storedCredential.credential_id) {
$scope.storedCredential.vault_id = $scope.active_vault.vault_id;
CredentialService.createCredential($scope.storedCredential).then(function () {
$scope.saving = false;
$scope.saving = false;
$location.path('/vault/' + $routeParams.vault_id);
NotificationService.showNotification($translate.instant('credential.created'), 5000);
@ -345,14 +345,26 @@
_credential.description = _credential.description.replace(regex, "");
}
CredentialService.updateCredential(_credential, _useKey).then(function () {
$scope.saving = false;
$scope.saving = false;
SettingsService.setSetting('edit_credential', null);
$location.path('/vault/' + $routeParams.vault_id);
NotificationService.showNotification($translate.instant('credential.updated'), 5000);
});
}
$scope.refreshListWithSaved();
};
};
$scope.refreshListWithSaved = function () {
var current_vault = $rootScope.vaultCache[$scope.active_vault.guid];
var cv_credentials = current_vault.credentials;
for (var i = 0; i < cv_credentials.length; i++) {
if (cv_credentials[i].credential_id === $scope.storedCredential.credential_id) {
cv_credentials[i] = $scope.storedCredential;
}
}
current_vault.credentials=cv_credentials;
$rootScope.vaultCache[$scope.active_vault.guid] = current_vault;
};
$scope.cancel = function () {
$location.path('/vault/' + $routeParams.vault_id);

View file

@ -41,6 +41,10 @@
}
$scope.removeHiddenStyles = function(){
document.getElementById('warning_bar').classList.remove('template-hidden');
};
$rootScope.$on('settings_loaded', function(){
if (SettingsService.isEnabled('disable_contextmenu')) {
document.addEventListener('contextmenu', function (event) {

View file

@ -23,7 +23,6 @@
(function () {
'use strict';
/**
* @ngdoc function
* @name passmanApp.controller:MenuCtrl
@ -32,15 +31,21 @@
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('MenuCtrl', ['$scope', 'VaultService', '$location', '$rootScope', 'TagService','SettingsService',
function ($scope, VaultService, $location, $rootScope, TagService, SettingsService) {
.controller('MenuCtrl', ['$scope', 'VaultService', '$location', '$rootScope', 'TagService','SettingsService', '$translate',
function ($scope, VaultService, $location, $rootScope, TagService, SettingsService, $translate) {
$rootScope.logout = function () {
//see vault.js:54
$rootScope.override_default_vault=true;
SettingsService.setSetting('defaultVaultPass', false);
TagService.resetTags();
$rootScope.$broadcast('logout');
$location.path('/');
};
$scope.removeHiddenStyles = function(){
document.getElementById('app-navigation').classList.remove('template-hidden');
};
$scope.selectedTags = [];
$scope.getTags = function ($query) {
return TagService.searchTag($query);
@ -77,12 +82,139 @@
$rootScope.$broadcast('selected_tags_updated', $scope.selectedTags);
}, true);
$scope.tagClicked = function (tag) {
$scope.selectedTags.push(tag);
$scope.tagSelected = function (tag) {
for (var i = 0; i < $scope.selectedTags.length; i++) {
if($scope.selectedTags[i].text === tag.text){
return true;
}
}
return false;
};
$scope.removeTagFromSelected = function (tag) {
var where =-1;
for (var i = 0; i < $scope.selectedTags.length; i++) {
if($scope.selectedTags[i].text === tag.text){
where=i;
}
}
if(where === -1){
//console.log("Cant remove selected Tag, Tag not present!");
}
$scope.selectedTags.splice(where, 1);
};
$scope.clearForm = function () {
document.getElementById('tagsearch').value="";
};
$scope.tagClickedString = function (tagtext) {
var tag=[];
tag.text=tagtext;
$scope.tagClicked(tag);
};
$scope.tagClicked = function (tag) {
//check if tag already selected
if(!$scope.tagSelected(tag)){
$scope.selectedTags.push(tag);
}else{
//console.log("Already selected Tag!");
$scope.removeTagFromSelected(tag);
}
};
//searchboxfix
var native_search = document.getElementById("searchbox");
if(native_search !== null){
native_search.nextElementSibling.addEventListener('click', function (e) {
$scope.$apply(function () {
$rootScope.$broadcast('nc_searchbox',"");
});
});
native_search.classList.remove('hidden');
native_search.addEventListener('keypress', function (e) {
if(e.keyCode === 13){
e.preventDefault();
}
});
native_search.addEventListener('keyup', function (e) {
$scope.$apply(function () {
$rootScope.$broadcast('nc_searchbox',native_search.value);
});
});
}
$scope.clickedNavigationItem="all";
$scope.filterCredentialBySpecial = function (string) {
$scope.clickedNavigationItem=string;
if(string !== "nav_trashbin"){
$scope.delete_time=0;
$rootScope.$broadcast('set_delete_time', $scope.delete_time);
}
$scope.selectedTags =[];
$rootScope.$broadcast('filterSpecial',string);
//close settings when item is selected
$scope.settingsShown=false;
};
$scope.collapsedDefaultValue=true;
$scope.tagCollapsibleOpen=VaultService.getVaultSetting("vaultTagCollapsedState",$scope.collapsedDefaultValue);
$scope.tagCollapsibleClicked = function () {
if (VaultService.getVaultSetting("vaultTagCollapsedState",$scope.collapsedDefaultValue) === true) {
VaultService.setVaultSetting("vaultTagCollapsedState",false);
} else {
VaultService.setVaultSetting("vaultTagCollapsedState",true);
}
};
$scope.tagCollapsibleState = function () {
if(VaultService.getVaultSetting('vaultTagCollapsedState',$scope.collapsedDefaultValue)){
return "";
}
return "open";
};
//this is needed, because the translation is not ready when the dom loads and the translation only returns the key.
//then the key is set, and the taginput is collapsed by angular. If the correct translation loads, the collapsed dom element does not update itself.
//here we set the value manually
$scope.initPlaceholder = function () {
$translate.onReady().then(function(){
var string=$translate.instant('navigation.advanced.filter');
document.getElementById("tags-input-outer").setAttribute("placeholder", string);
document.getElementById("tags-input-outer").firstChild.firstChild.childNodes[1].setAttribute("placeholder", string);
});
};
$scope.legacyNavbarDefault=true;
$scope.legacyNavbarAlreadyInitialized=false;
if (typeof $scope.legacyNavbar === 'undefined') {
$scope.legacyNavbar = $scope.legacyNavbarDefault;
}
$scope.$watch('legacyNavbar', function(newValue, oldValue) {
VaultService.setVaultSetting("vaultNavBarLegacy",newValue);
});
$scope.initializeNavbar = function () {
if($scope.legacyNavbarAlreadyInitialized){
return;
}
$scope.legacyNavbar = VaultService.getVaultSetting('vaultNavBarLegacy',$scope.legacyNavbarDefault);
$scope.legacyNavbarAlreadyInitialized=true;
};
$rootScope.$on('credentials_loaded', function () {
$rootScope.$broadcast('selected_tags_updated', $scope.selectedTags);
$scope.initializeNavbar();
});
$scope.available_tags = TagService.getTags();
@ -91,10 +223,14 @@
if ($scope.selectedTags.length === 0) {
return TagService.getTags();
} else {
return $scope.filtered_tags;
return TagService.getTags();
//Always show all tags
//return $scope.filtered_tags;
}
}, function (tags) {
$scope.available_tags = tags;
//Always show all tags
//$scope.available_tags = tags;
$scope.available_tags = TagService.getTags();
}, true);
$scope.toggleDeleteTime = function () {
@ -102,8 +238,9 @@
$scope.delete_time = 0;
} else {
$scope.delete_time = 1;
this.filterCredentialBySpecial('nav_trashbin');
}
$rootScope.$broadcast('set_delete_time', $scope.delete_time);
};
}]);
}());
}());

View file

@ -46,7 +46,11 @@
var vault = vaults[i];
if (vault.guid === default_vault.guid) {
$scope.default_vault = true;
$scope.list_selected_vault = vault;
//This prevents the opening of the default vault if the user logs out
if(!$rootScope.override_default_vault){
$scope.list_selected_vault = vault;
$rootScope.override_default_vault=false;
}
SettingsService.setSetting('defaultVault', vault);
if (SettingsService.getSetting('defaultVaultPass')) {
$location.path('/vault/' + vault.guid);
@ -219,7 +223,8 @@
};
$scope.createVault = function (vault_name, vault_key, vault_key2) {
$scope.createVault = function (vault_name, vault_key, vault_key2) {
if (vault_key !== vault_key2) {
$scope.error = $translate.instant('password.do.not.match');
return;

View file

@ -50,12 +50,12 @@
'<div class="tools">' +
'<div class="cell" ng-if="toggle" tooltip="tggltxt" ng-click="toggleVisibility()"><i class="fa" ng-class="{\'fa-eye\': !valueVisible, \'fa-eye-slash\': valueVisible }"></i></div>' +
'<div class="cell" ng-if="isLink"><a ng-href="{{value}}" target="_blank" rel="nofollow noopener noreferrer"><i tooltip="\'Open in new window\'" class="link fa fa-external-link"></i></a></div>' +
'<div class="cell" ngclipboard-success="onSuccess(e);" ngclipboard-error="onError(e);" ngclipboard data-clipboard-text="{{value}}"><i tooltip="copy_msg" class="fa fa-files-o"></i></div>' +
'<div class="cell" ngclipboard-success="onSuccess(e);" ngclipboard-error="onError(e);" ngclipboard data-clipboard-text="{{value}}"><i tooltip="copy_msg" class="fa fa-files-o"></i></div>' +
'</div></span>',
link: function (scope) {
var expression = /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/gi;
var regex = new RegExp(expression);
$translate(['toggle.visibility', 'copy', 'copied']).then(function (translations) {
$translate(['toggle.visibility','copy.field', 'copy', 'copied']).then(function (translations) {
scope.tggltxt = translations['toggle.visibility'];
scope.copy_msg = translations['copy.field'];
});

View file

@ -32,7 +32,7 @@
angular.module('passmanApp').directive('credentialIcon', [
'$window', function($window) {
return {
template: '<img ng-src="{{ iconUrl }}" width="16">',
template: '<img ng-src="{{ iconUrl }}" class="icon-image">',
restrict: 'E',
scope: {
credential: '=',

View file

@ -66,7 +66,7 @@
return false;
} else {
_activeVault.vault_settings[key] = value;
_this.updateVault(_activeVault);
this.updateVault(_activeVault);
}
},

View file

@ -9,7 +9,7 @@ angular.module('views/credential_revisions.html', []).run(['$templateCache', fun
angular.module('views/edit_credential.html', []).run(['$templateCache', function ($templateCache) {
'use strict';
$templateCache.put('views/edit_credential.html',
'<div id="controls"><div class="actions creatable"><div class="breadcrumb"><div class="crumb svg ui-droppable" data-dir="/"><a ng-click="logout()"><i class="fa fa-home"></i></a></div><div class="crumb svg" data-dir="/Test"><a ng-click="cancel()">{{active_vault.name}}</a></div><div class="crumb svg last" data-dir="/Test"><a ng-if="storedCredential.credential_id">{{ \'edit.credential\' | translate}} "{{storedCredential.label}}"</a> <a ng-if="!storedCredential.credential_id">{{ \'create.credential\' | translate}}</a></div></div></div></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 color="\'true\'">{{tab.title}}<div class="indicator" use-theme negative="\'true\'"></div></li></ul><div class="tab_container edit_credential" use-theme type="\'border-top-color\'"><div ng-include="currentTab.url"></div><button ng-click="saveCredential()" ng-disabled="saving"><i class="fa fa-spinner fa-spin" ng-show="saving"></i> {{ \'save\' | translate}}</button> <button ng-click="cancel()">{{ \'cancel\' | translate}}</button></div>');
'<div id="passman-controls"><div class="breadcrumb"><div class="breadcrumb"><div class="crumb svg ui-droppable" data-dir="/"><a ng-click="logout()"><i class="fa fa-home"></i></a></div><div class="crumb svg" data-dir="/Test"><a ng-click="cancel()">{{active_vault.name}}</a></div><div class="crumb svg last" data-dir="/Test"><a ng-if="storedCredential.credential_id">{{ \'edit.credential\' | translate}} "{{storedCredential.label}}"</a> <a ng-if="!storedCredential.credential_id">{{ \'create.credential\' | translate}}</a></div></div></div></div><div><ul class="tab_header"><li ng-repeat="tab in tabs track by $index" class="tab" ng-class="isActiveTab(tab)? \'active\' : \'inactive\'" ng-click="onClickTab(tab)" use-theme color="\'true\'">{{tab.title}}<div class="indicator" use-theme negative="\'true\'"></div></li></ul><div class="tab_container edit_credential" use-theme type="\'border-top-color\'"><div ng-include="currentTab.url"></div><button ng-click="saveCredential()" ng-disabled="saving"><i class="fa fa-spinner fa-spin" ng-show="saving"></i> {{ \'save\' | translate}}</button> <button ng-click="cancel()">{{ \'cancel\' | translate}}</button></div></div>');
}]);
angular.module('views/partials/credential_template.html', []).run(['$templateCache', function ($templateCache) {
@ -107,7 +107,7 @@ angular.module('views/partials/forms/share_credential/link_sharing.html', []).ru
angular.module('views/partials/icon-picker.html', []).run(['$templateCache', function ($templateCache) {
'use strict';
$templateCache.put('views/partials/icon-picker.html',
'<div><div class="cell"><credential-icon credential="credential"></credential-icon></div><div style="display: none" id="iconPicker" title="{{ \'pick.icon\' | translate }}"><div class="iconList"><div ng-repeat="(groupName, icons) in iconGroups"><h2 style="clear: both" id="{{groupName}}">{{groupName}}</h2><div class="icon" ng-repeat="icon in icons" ng-click="selectIcon(icon)"><img ng-src="{{icon.url}}" height="32"></div></div></div><div class="iconModifier"><div ng-if="selectedIcon">{{ \'selected.icon\' | translate}}:<br><img ng-src="{{selectedIcon.url}}" height="32"><br><button ng-click="useIcon()" ng-if="selectedIcon">{{ \'use.icon\' | translate}}</button></div></div></div></div>');
'<div class="cell icon-category-auth"></div><div style="display: none" id="iconPicker" title="{{ \'pick.icon\' | translate }}"><div class="iconList"><div ng-repeat="(groupName, icons) in iconGroups"><h2 style="clear: both" id="{{groupName}}">{{groupName}}</h2><div class="icon" ng-repeat="icon in icons" ng-click="selectIcon(icon)"><img ng-src="{{icon.url}}" height="32"></div></div></div><div class="iconModifier"><div ng-if="selectedIcon">{{ \'selected.icon\' | translate}}:<br><img ng-src="{{selectedIcon.url}}" height="32"><br><button ng-click="useIcon()" ng-if="selectedIcon">{{ \'use.icon\' | translate}}</button></div></div></div>');
}]);
angular.module('views/partials/password-meter.html', []).run(['$templateCache', function ($templateCache) {
@ -119,7 +119,7 @@ angular.module('views/partials/password-meter.html', []).run(['$templateCache',
angular.module('views/settings.html', []).run(['$templateCache', function ($templateCache) {
'use strict';
$templateCache.put('views/settings.html',
'<div id="controls"><div class="actions creatable"><div class="breadcrumb"><div class="crumb svg ui-droppable"><a ng-click="logout()"><i class="fa fa-home"></i></a></div><div class="crumb svg"><a ng-click="cancel()">{{active_vault.name}}</a></div><div class="crumb svg last"><a>{{ \'settings\' | translate}}</a></div></div></div></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 color="\'true\'">{{tab.title}}<div class="indicator" use-theme negative="\'true\'"></div></li></ul><div class="tab_container settings edit_credential"><div ng-include="currentTab.url"></div></div>');
'<div id="passman-controls"><div class="breadcrumb"><div class="breadcrumb"><div class="crumb svg ui-droppable" data-dir="/"><a ng-click="logout()"><i class="fa fa-home"></i></a></div><div class="crumb svg"><a ng-click="cancel()">{{active_vault.name}}</a></div><div class="crumb svg last"><a>{{ \'settings\' | translate}}</a></div></div></div></div><div><ul class="tab_header"><li ng-repeat="tab in tabs track by $index" class="tab" ng-class="isActiveTab(tab)? \'active\' : \'inactive\'" ng-click="onClickTab(tab)" use-theme color="\'true\'">{{tab.title | translate}}<div class="indicator" use-theme negative="\'true\'"></div></li></ul><div class="tab_container settings edit_credential" use-theme type="\'border-top-color\'"><div ng-include="currentTab.url"></div></div></div>');
}]);
angular.module('views/share_credential.html', []).run(['$templateCache', function ($templateCache) {
@ -131,8 +131,8 @@ angular.module('views/share_credential.html', []).run(['$templateCache', functio
angular.module('views/show_vault.html', []).run(['$templateCache', function ($templateCache) {
'use strict';
$templateCache.put('views/show_vault.html',
'<div off-click="closeSelected()" off-click-filter="\'.download-js-link, .sidebar-shown\'"><div id="passman-controls" ng-class="{ \'sidebar-shown\': selectedCredential }"><div class="breadcrumb"><div class="breadcrumb"><div class="crumb svg ui-droppable" data-dir="/"><a ng-click="logout()"><i class="fa fa-home"></i></a></div><div class="crumb svg last" ng-click="clearState()"><span>{{active_vault.name}}</span></div></div></div><div class="actions creatable"><span ng-click="addCredential()" class="button new"><span>+</span></span></div><div class="title" credential-counter="filtered_credentials" vault="active_vault" delete-time="delete_time" filters="filterOptions"></div><div class="searchboxContainer" ng-init="filterOptionShown = false;" off-click="filterOptionShown = false;"><input type="text" ng-model="filterOptions.filterText" class="searchbox" id="searchBox" placeholder="{{\'search.credential\' | translate}}" select-on-click clear-btn ng-click="filterOptionShown = true;"><div class="searchOptions" ng-show="filterOptionShown"><input type="checkbox" ng-model="filterOptions.useRegex"> {{ \'use.regex\' | translate }}</div></div><div class="viewModes"><div class="view-mode" ng-class="{\'active\': view_mode === \'list\' }" ng-click="switchViewMode(\'list\')"><i class="fa fa-list"></i></div><div class="view-mode" ng-class="{\'active\': view_mode === \'grid\' }" ng-click="switchViewMode(\'grid\')"><i class="fa fa-th-large"></i></div></div></div><div class="loaderContainer" ng-if="show_spinner"><div class="loader" use-theme type="\'border-bottom-color\'"></div></div><div ng-init="menuOpen = false;"><table class="credential-table" ng-if="view_mode === \'list\'"><tr ng-repeat="credential in filtered_credentials | orderBy:\'label\'" ng-if="showCredentialRow(credential)" ng-click="selectCredential(credential)" ng-dblclick="editCredential(credential)" ng-class="{\'selected\': selectedCredential.credential_id == credential.credential_id}"><td><span class="tags"><span class="tag" ng-repeat="tag in credential.tags_raw">{{ ::tag.text}}</span> </span><span class="icon" ng-if="credential.url"><credential-icon credential="credential"></credential-icon></span><span class="icon" ng-if="!credential.url"><i class="fa fa-lock" ng-if="!credential.acl && !credential.shared_key"></i> <i class="fa fa-share-alt" ng-if="credential.acl"></i> <i class="fa fa-share-alt-square" ng-if="credential.shared_key"></i> </span><span class="label">{{ ::credential.label}}</span></td></tr></table><ul class="grid-view" ng-if="view_mode === \'grid\'"><li class="credential" ng-repeat="credential in filtered_credentials | orderBy:\'label\'" ng-if="credential.hidden == 0 && showCredentialRow(credential)" ng-click="selectCredential(credential)" use-theme type="\'border-color\'"><div class="credential_content"><div class="label">{{ ::credential.label}}</div><div class="tags"><div class="tag" ng-repeat="tag in credential.tags_raw">{{ ::tag.text}}</div></div></div></li></ul></div><div id="app-sidebar" class="detailsView scroll-container app_sidebar" ng-show="selectedCredential"><h2>{{selectedCredential.label}}</h2><span class="close icon-close" ng-click="closeSelected()" alt="Close"></span><div credential-template="selectedCredential"></div><div ng-show="selectedCredential"><div><button class="button" ng-click="editCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)"><span class="fa fa-edit"></span> {{ \'edit\' | translate}}</button> <button class="button" ng-click="deleteCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)"><span class="fa fa-trash"></span> {{ \'delete\' | translate}}</button> <button class="button" ng-click="shareCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && selectedCredential.acl === undefined &&\n' +
' (settings.user_sharing_enabled === 1 || settings.user_sharing_enabled === \'1\' || settings.link_sharing_enabled === 1 || settings.link_sharing_enabled === \'1\')"><span class="fa fa-share"></span> {{ \'share\' | translate}}</button> <button class="button" ng-click="getRevisions(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.HISTORY)"><span class="fa fa-undo"></span> {{ \'revisions\' | translate}}</button> <button class="button" ng-if="selectedCredential.delete_time > 0" ng-click="recoverCredential(selectedCredential) && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)"><span class="fa fa-recycle"></span> {{\'recover\' | translate}}</button> <button class="button" ng-if="selectedCredential.delete_time > 0" ng-click="destroyCredential(selectedCredential)"><span class="fa fa-bomb"></span> {{\'destroy\' | translate}}</button></div></div></div></div><div class="share_popup" style="display: none">{{ \'sharereq.title\' | translate}}<br><p>{{ \'sharereq.line1\' | translate}}</p>{{active_vault.vault_id}}<table class="table"><thead><tr><td>{{ \'label\' | translate}}</td><td>{{ \'permissions\' | translate}}</td><td>{{ \'received.from\' | translate}}</td><td>{{ \'date\' | translate}}</td></tr></thead><tr ng-repeat="share_request in incoming_share_requests" ng-if="share_request.target_vault_id == active_vault.vault_id"><td>{{share_request.credential_label}}</td><td>{{share_request.permissions}}</td><td>{{share_request.from_user_id}}</td><td>{{share_request.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td><td><span class="link" ng-click="acceptShareRequest(share_request)">{{ \'accept\' | translate}}</span> | <span class="link" ng-click="declineShareRequest(share_request)">{{ \'decline\' | translate}}</span></td></tr></table></div>');
'<div class="main_list" off-click="closeSelected()" off-click-filter="\'.download-js-link, .sidebar-shown\'"><div id="passman-controls" ng-class="{ \'sidebar-shown\': selectedCredential }"><div class="breadcrumb"><div class="breadcrumb"><div class="crumb svg ui-droppable" data-dir="/"><a ng-click="logout()"><i class="fa fa-home"></i></a></div><div class="crumb svg" ng-click="clearState()"><a>{{active_vault.name}}</a></div><div class="crumb svg last" ng-hide="delete_time>0"><a ng-click="addCredential()">{{ \'New\' | translate}}</a></div></div></div><div class="title" credential-counter="filtered_credentials" vault="active_vault" delete-time="delete_time" filters="filterOptions"></div><div class="searchboxContainer" ng-init="filterOptionShown = false;" off-click="filterOptionShown = false;"><input type="text" ng-model="filterOptions.filterText" class="searchbox" id="searchBox" placeholder="{{\'search.credential\' | translate}}" select-on-click clear-btn ng-click="filterOptionShown = true;"><div class="searchOptions" ng-show="filterOptionShown"><input type="checkbox" ng-model="filterOptions.useRegex"> {{ \'use.regex\' | translate }}</div></div><div class="viewModes"><div class="view-mode" ng-class="{\'active\': view_mode === \'list\' }" ng-click="switchViewMode(\'list\')"><i class="fa fa-list"></i></div><div class="view-mode" ng-class="{\'active\': view_mode === \'grid\' }" ng-click="switchViewMode(\'grid\')"><i class="fa fa-th-large"></i></div></div></div><div class="loaderContainer" ng-if="show_spinner"><div class="loader" use-theme type="\'border-bottom-color\'"></div></div><div ng-init="menuOpen = false;"><table class="credential-table" ng-if="view_mode === \'list\'"><tr ng-repeat="credential in filtered_credentials | orderBy:\'label\'" ng-if="showCredentialRow(credential)" ng-click="selectCredential(credential)" ng-dblclick="editCredential(credential)" ng-class="{\'selected\': selectedCredential.credential_id == credential.credential_id}"><td><span class="tags"><span class="tag" ng-repeat="tag in credential.tags_raw">{{ ::tag.text}}</span> </span><span class="icon" ng-if="credential.url"><credential-icon credential="credential"></credential-icon></span><span class="icon" ng-if="!credential.url"><i class="fa fa-lock" ng-if="!credential.acl && !credential.shared_key"></i> <i class="fa fa-share-alt" ng-if="credential.acl"></i> <i class="fa fa-share-alt-square" ng-if="credential.shared_key"></i> </span><a class="label">{{ ::credential.label}}</a></td></tr></table><ul class="grid-view" ng-if="view_mode === \'grid\'"><li class="credential" ng-repeat="credential in filtered_credentials | orderBy:\'label\'" ng-if="credential.hidden == 0 && showCredentialRow(credential)" ng-click="selectCredential(credential)" use-theme type="\'border-color\'"><div class="credential_content"><div><span class="icon" ng-if="credential.url"><credential-icon credential="credential"></credential-icon></span><span class="icon" ng-if="!credential.url"><i class="fa fa-lock" ng-if="!credential.acl && !credential.shared_key"></i> <i class="fa fa-share-alt" ng-if="credential.acl"></i> <i class="fa fa-share-alt-square" ng-if="credential.shared_key"></i></span><div class="label">{{ ::credential.label}}</div></div><div class="tags"><div class="tag" ng-repeat="tag in credential.tags_raw">{{ ::tag.text}}</div></div></div></li></ul></div></div><div id="app-sidebar" class="app_sidebar" ng-show="selectedCredential"><span class="close icon-close" ng-click="closeSelected()" alt="Close"></span><div class="sidebar"><span class="icon sidebar-icon" ng-if="selectedCredential.url"><credential-icon credential="selectedCredential"></credential-icon></span><span class="icon sidebar-icon" ng-if="!selectedCredential.url"><credential-icon credential="selectedCredential"></credential-icon></span><h2 class="sidebar-label">{{selectedCredential.label}}</h2></div><div credential-template="selectedCredential"></div><div ng-show="selectedCredential"><div><button class="button" ng-click="editCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)"><span class="fa fa-edit"></span> {{ \'edit\' | translate}}</button> <button class="button" ng-click="deleteCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)"><span class="fa fa-trash"></span> {{ \'delete\' | translate}}</button> <button class="button" ng-click="shareCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && selectedCredential.acl === undefined &&\n' +
' (settings.user_sharing_enabled === 1 || settings.user_sharing_enabled === \'1\' || settings.link_sharing_enabled === 1 || settings.link_sharing_enabled === \'1\')"><span class="fa fa-share"></span> {{ \'share\' | translate}}</button> <button class="button" ng-click="getRevisions(selectedCredential)" ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.HISTORY)"><span class="fa fa-undo"></span> {{ \'revisions\' | translate}}</button> <button class="button" ng-if="selectedCredential.delete_time > 0" ng-click="recoverCredential(selectedCredential) && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)"><span class="fa fa-recycle"></span> {{\'recover\' | translate}}</button> <button class="button" ng-if="selectedCredential.delete_time > 0" ng-click="destroyCredential(selectedCredential)"><span class="fa fa-bomb"></span> {{\'destroy\' | translate}}</button></div></div></div><div class="share_popup" style="display: none">{{ \'sharereq.title\' | translate}}<br><p>{{ \'sharereq.line1\' | translate}}</p>{{active_vault.vault_id}}<table class="table"><thead><tr><td>{{ \'label\' | translate}}</td><td>{{ \'permissions\' | translate}}</td><td>{{ \'received.from\' | translate}}</td><td>{{ \'date\' | translate}}</td></tr></thead><tr ng-repeat="share_request in incoming_share_requests" ng-if="share_request.target_vault_id == active_vault.vault_id"><td>{{share_request.credential_label}}</td><td>{{share_request.permissions}}</td><td>{{share_request.from_user_id}}</td><td>{{share_request.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td><td><span class="link" ng-click="acceptShareRequest(share_request)">{{ \'accept\' | translate}}</span> | <span class="link" ng-click="declineShareRequest(share_request)">{{ \'decline\' | translate}}</span></td></tr></table></div>');
}]);
angular.module('views/vault_req_deletion.html', []).run(['$templateCache', function ($templateCache) {

View file

@ -20,7 +20,7 @@ module.exports = function (config) {
// list of files / patterns to load in the browser
files: [
'../../core/vendor/jquery/dist/jquery.js',
'../../core/vendor/underscore/underscore.js',
'../../core/vendor/underscore/underscore-min.js',
'js/vendor/angular/angular.min.js',
'tests/unit/js/mocks/*.js',
'js/vendor/angular-mocks/angular-mocks.js',

View file

@ -5,7 +5,7 @@
"karma-verbose-reporter": "0.0.3"
},
"dependencies": {
"grunt": "~0.4.5",
"grunt": "~1.0.3",
"grunt-cli": "~1.2.0",
"grunt-contrib-clean": "^1.0.0",
"grunt-contrib-concat": "^1.0.1",

View file

@ -12,13 +12,4 @@
#requests-table{
width: 100%;
}
.link{
color: rgb(0, 102, 255) !important;
cursor: pointer;
}
.link:hover{
text-decoration: underline;
}
}

View file

@ -32,18 +32,20 @@
@import 'share_credential';
@import 'settings';
#app-settings-content:not(.ng-hide) {
height: 90px;
display: inherit !important;
padding: 0;
transition: height 0.15s ease-out;
.template-hidden{
display: none !important;
}
#app-settings-content.ng-hide{
.hide-animation {
display: inherit !important;
height: 0;
padding: 0;
transition: height 0.15s ease-in;
transition: ease-in-out .15s;
}
.hide-animation.ng-hide {
opacity: 0;
}
.ui-dialog{
z-index: 9999;
}
@ -54,22 +56,18 @@
}
}
//
#app-content #app-content-wrapper #passman-controls {
border-bottom: 1px solid #c9c9c9;
}
#passman-controls {
box-sizing: border-box;
position: fixed;
top: 45px;
margin: -45px 0 0;
right: 0;
left: 0;
border-bottom: 1px solid #c9c9c9;
padding: 0 !important;
margin: 0;
background-color: rgba(255, 255, 255, .95);
z-index: 50;
-webkit-user-select: none;
@ -78,6 +76,15 @@
user-select: none;
height: 44px !important;
.breadcrumb{
//Move Homeicon to the right to prevent overlap with burgermenu
@media only screen and (max-width: 769px) {
padding-left: 15px;
}
.addCredential{
padding-top: 1px;
}
}
}
@media only screen and (max-width: 768px){
#passman-controls{
@ -86,8 +93,8 @@
}
@media only screen and (min-width: 768px){
#app-navigation+#app-content #passman-controls {
left: 250px;
width: calc( 100% - 250px ) !important;
left: 300px;
width: calc( 100% - 300px ) !important;
}
}
#passman-controls .button, #passman-controls, #passman-controls input[type='submit'], #passman-controls input[type='text'], #passman-controls input[type='password'], #passman-controls select {

View file

@ -20,14 +20,77 @@
*
*/
//override nc style to fix wrong offset
#content {
padding-top: 47px !important; // 45px but +2 because of borders
height: 100%;
width: 100%;
}
//fix for different heights of passwordicon
.icon-image{
width: 16px;
}
//fix for ui-element behind Background
.angularjs-datetime-picker{
z-index: 1000;
}
.link{
color:var(--color-primary);
}
//this fixes the scrollbars, because passman-contols are shown above the sidebar.
#app-sidebar{
height: auto;
.sidebar{
display: inline-block;
.sidebar-icon {
margin-right: 15px;
.icon-image{
width: 44px;
}
i {
width: 44px;
}
}
.sidebar-label{
float:right;
line-height: 44px;
}
}
}
.vaultlist_sidebar_hidden{
width: 100vw !important;
margin-left: 0px !important;
}
#app-content {
margin-left: 300px;
@media only screen and (max-width: 769px) {
width: 100vw;
}
@media only screen and (min-width: 770px) {
width: calc(100vw - 300px);
}
overflow-x: hidden;
//width: 100%;
#app-content-wrapper {
min-height: 95%;
display:flex;
//hack for missing separatorbar when app-sidebar is opened
height: calc(100vh - 49px);
#passman-controls {
text-align: center;
&.sidebar-shown {
padding-right: 27% !important;
//padding-right: 27% !important;
.title {
@media screen and (max-width: 765px) {
display: none;
@ -53,6 +116,9 @@
display: none;
}
}
.breadcrumb {
float: left;
}
.actions.creatable {
float: left;
overflow: hidden;
@ -108,7 +174,9 @@
}
.searchboxContainer {
display: inline-block;
/*display: inline-block;*/
visibility: hidden;
display: none;
margin-right: 14px;
float: right;
.searchbox {
@ -136,9 +204,9 @@
@include border-bottom-radius(3px);
}
}
.credential-table {
width: 100%;
margin-top: 44px;
tr:hover {
background-color: darken(#fff, 4%);
}
@ -212,7 +280,9 @@
}
.grid-view {
margin-top: 44px;
width: 100%;
height: 100%;
//margin-top: 44px;
display: flex;
flex-wrap: wrap;
.credential {
@ -228,20 +298,26 @@
width: 100%;
cursor: pointer;
font-size: 1.75em;
text-align: center;
//text-align: center;
.label {
padding-top: 0.5em;
padding-left: 1em;
//padding-left: 1em;
padding-right: 1em;
line-height: 1.3em;
word-wrap: break-word;
float: right;
}
.icon{
}
.tags {
margin-bottom: 0.5em;
margin: 0 0 auto;
text-align: right;
//margin-bottom: 0.5em;
.tag {
color: #000 !important;
margin-top: 5px;
display: inline-block;
left:0;
}
}
}
@ -305,6 +381,9 @@
float: left;
}
}
.password-settings-padding-left-fix{
padding-left: 0 !important;
}
}
.field-value {
.valueInput {
@ -318,7 +397,7 @@
}
.selectType {
padding-left: 0;
margin-left: -4px;
margin-left: 0px;
select {
@include border-left-radius(0);
}
@ -378,8 +457,40 @@
.otpText {
padding-right: 10px;
}
.import-selection{
select{
margin-left: 15px;
}
}
}
.main_list{
flex:1;
float:left;
height:auto;
overflow:auto;
width:100%;
.share{
overflow:hidden;
}
.nopasswords{
margin-right: auto;
margin-left: auto;
margin-top: 10%;
text-align: center;
}
.belowList{
margin-right: auto;
margin-left: auto;
margin-top: 1%;
text-align: center;
}
}
.app_sidebar {
float:right;
h2 {
margin-bottom: 10px;
font-weight: 400;
@ -430,12 +541,12 @@
}
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 70%;
max-width: 100%;
}
.tools {
margin-left: 10px;
margin-top: 8px;
overflow: hidden;
float: left;
.cell {
@ -468,7 +579,7 @@
width: 120px;
margin-top: 30px;
margin-left: -60px;
top: 50%;
top: 30%;
left: 50%;
position: absolute;
}
@ -526,13 +637,14 @@
}
.btn-danger {
color: #fff;
color: #000000;
background-color: #ff0000;
}
.icon-label {
overflow: hidden;
input {
width: calc(100% - 45px) !important;
width: calc(100% - 28px) !important;
float: left;
background: #fff;
color: #555;
@ -541,7 +653,7 @@
border: 1px solid #ddd;
outline: none;
border-radius: 3px;
margin: 3px 3px 3px 0;
margin: 3px 0 3px 0;
padding: 7px 6px 5px;
font-size: 13px;
@include border-left-radius(0)
@ -549,19 +661,14 @@
.icon-picker {
float: left;
margin-top: 3px;
margin-left: -3px;
@include border-left-radius(3px);
.cell {
height: 32px;
padding: 7px 12px 2px 12px;
display: inline-block;
font-size: 14px;
border: 1px solid #ddd;
background-color: lighten(#ddd, 5%);
cursor: pointer;
@include border-left-radius(6px);
img {
height: 16px;
}
}
.cell:hover {
color: rgb(0, 102, 255);
@ -589,4 +696,4 @@
float: right;
width: calc(40% - 10px);
}
}
}

View file

@ -23,40 +23,90 @@
.settings-container {
div {
padding-left: 15px;
}
button {
width: 80%;
margin-left: 15px;
margin-right: 15px;
}
}
.settings-container-label {
padding-left: 15px;
}
#app-navigation > ul{
padding-bottom: 80px;
> li > a{
padding-left: 12px !important;
z-index: auto;
}
> li {
display: block;
}
}
.nav-trashbin {
position: fixed !important;
bottom: 44px;
//position: fixed !important;
//bottom: 44px;
width: inherit !important;
border-right: 1px solid #eee;
a {
&.active{
border-left: 3px solid #0082c9;
//border-left: 3px solid #0082c9;
background-image: var(--icon-delete-e9322d);
}
background-color: #fff !important;
opacity: 1 !important;
z-index: 140;
padding: 0 20px;
//padding: 0 20px;
.fa {
margin-right: 15px;
}
}
}
//Overrides transparent entry bullet on hover from server
#app-navigation{
.collapsible:hover .app-navigation-entry-bullet{
background: var(--color-primary) !important;
}
}
#app-navigation {
a{
.selected{
opacity: 1!important;
box-shadow: inset 4px 0 var(--color-primary)!important;
}
}
li{
.app-navigation-entry-bullet-color {
background-color: var(--color-primary);
}
.bullet-color-red {
background-color: #ff0000;
}
.bullet-color-yellow {
background-color: #ebbb00;
}
.bullet-color-green {
background-color: #4db728;
}
.highlight-selected{
background-color: var(--color-primary);
}
.autocomplete{
position: relative;
}
a.taginput{
opacity: 1;
}
@ -73,4 +123,13 @@
> ul ul {
display: inherit !important;
}
}
.hidden-list{
display: none !important;
}
//source https://material.io/tools/icons/?icon=restore&style=baseline
.icon-expired{
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path d='M0 0h24v24H0z' fill='none'/><path d='M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z'/></svg>");
}

View file

@ -36,11 +36,4 @@
.button-red:hover{
background: lighten(#ce3702, 2%);
color: #fff;
}
.link{
color: rgb(0, 102, 255) !important;
cursor: pointer;
}
.link:hover{
text-decoration: underline;
}

View file

@ -23,7 +23,7 @@
.pw-gen{
overflow:hidden;
input{
width: calc(100% - 80px) !important;
width: calc(100% - 76px) !important;
float: left;
background: #fff;
color: #555;
@ -41,6 +41,7 @@
float: left;
margin-top: 3px;
margin-left: -3px;
padding-bottom:1px;
.cell{
padding: 5px;
display: inline-block;

View file

@ -21,7 +21,9 @@
*/
.tab_header {
margin: 44px 0 0;
width: calc(100vw - 300px);
// margin: 44px 0 0;
margin: 0 0 0;
list-style: none;
padding: 0;
li.tab:first-child {
@ -45,9 +47,15 @@
display: none;
}
}
li.inactive {
background-color: #fff !important;
color: unset !important;
}
li.active {
color: #fff;
position: relative;
//position: relative;
.indicator {
display: inline-block;
position: absolute;
@ -60,10 +68,9 @@
}
.tab_container {
border: 1px solid;
border-color: #eee;
border: 1px solid #eee;
border-top-color: #0082c9;
border-bottom: 0;
border-bottom-width: 0;
clear: both;
padding: 0 1em;
}

View file

@ -30,6 +30,16 @@ header {
padding-top: 0;
}
.share-controller{
width: 100%;
.share-container{
margin-top: 50px;
margin-left: auto;
margin-right: auto;
width: 25%;
}
}
.credential_container{
margin-top: 20px;
margin-bottom: 20px;
@ -45,6 +55,7 @@ header {
}
button, .text{
margin: 0 auto;
margin-bottom: 25px;
display: block;
i{
margin-right: 5px;

View file

@ -42,6 +42,9 @@
}
.tab_container.settings {
textarea{
height: 300px;
}
margin-bottom: 50px;
}
@ -66,4 +69,4 @@
text-align: left;
padding: 3px 5px;
}
}
}

View file

@ -22,6 +22,10 @@
.sharing_table {
.button{
min-height: 42px;
margin: 5px 0 0 0;
}
td:first-child {
width: 55%;
@ -52,6 +56,10 @@
}
}
.shared_table {
.pending{
margin-right: 10px;
}
.fa-trash {
cursor: pointer;
}

View file

@ -26,7 +26,7 @@
padding: 12px;
font-weight: bold;
text-align: center;
z-index: 800;
z-index: 1800;
background-color: red;
color: white;
.fa-times{
@ -36,9 +36,8 @@
}
}
.vault_wrapper{
margin: 0 auto;
margin-top: 20px;
width: 100%;
margin:0 auto auto auto;
max-width: 420px;
@include border-radius(5px);
box-shadow: 0 1px 1px #777;

View file

@ -118,60 +118,121 @@ style('passman', 'app');
?>
<div id="app" ng-app="passmanApp" ng-controller="MainCtrl">
<div id="logoutTimer"> </div>
<div class="warning_bar" ng-if="using_http && http_warning_hidden == false">
{{ 'http.warning' | translate }}
<i class="fa fa-times fa-2x" alt="Close" ng-click="setHttpWarning(true);"></i>
</div>
<div id="logoutTimer"></div>
<div id="warning_bar" class="warning_bar template-hidden" ng-if="using_http && http_warning_hidden == false" ng-init="removeHiddenStyles()">
{{ 'http.warning' | translate }}
<i class="fa fa-times fa-2x" alt="Close" ng-click="setHttpWarning(true);"></i>
</div>
<div id="app-navigation" ng-show="selectedVault" ng-controller="MenuCtrl">
<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>
<div id="app-navigation" class="template-hidden" ng-if="selectedVault" ng-controller="MenuCtrl" ng-init="removeHiddenStyles()">
<ul class="with-icon" ng-class="{ 'hidden-list': !legacyNavbar }" >
<li ng-repeat="tag in available_tags | orderBy:'text'" ng-if="selectedTags.indexOf(tag) == -1">
<a class="nav-icon-systemtagsfilter svg" 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' | translate }}
</a>
</li>
</ul>
<li>
<a ng-class="{selected: clickedNavigationItem=='all'}" class="icon-toggle svg" ng-click="filterCredentialBySpecial('all')">{{ 'navigation.show.all' | translate }}</a>
</li>
<li class="collapsible" ng-class="tagCollapsibleState()">
<button class="collapse" ng-click="tagCollapsibleClicked()"></button>
<a href="" class="icon-tag" ng-click="tagCollapsibleClicked()">{{ 'navigation.tags' | translate }}</a>
<ul>
<li class="taginput">
<a class="icon-search taginput">
<form ng-submit="tagClickedString(taginput); clearForm();">
<input id="tagsearch" list="tags" ng-model="taginput" placeholder="{{ 'navigation.tags.search' | translate }}" />
<datalist id="tags">
<option ng-repeat="qtag in getTags($query)" value="{{qtag.text}}">
</datalist>
</form>
</a>
</li>
<div id="app-settings" ng-init="settingsShown = false;">
<div id="app-settings-header">
<button class="settings-button"
ng-click="settingsShown = !settingsShown"
>{{ 'settings' | translate }}
</button>
</div>
<div id="app-settings-content" ng-show="settingsShown">
<!-- Your settings in here -->
<div class="settings-container">
<div><a class="link" ng-href="#/vault/{{active_vault.guid}}/settings">{{ 'settings' | translate }}</a></div>
<div><span class="link" ng-click="logout()">{{'logout' | translate }}</span></div>
<div><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2" target="_blank" class="link">{{ 'donate' | translate }}</a></div>
<div ng-show="session_time_left">
<small>{{'session.time.left' | translate:translationData}}</small>
</div>
</div>
</div>
</div>
</div>
<li ng-repeat="tag in available_tags | orderBy:'text'">
<div ng-if="tagSelected(tag)"
class="app-navigation-entry-bullet app-navigation-entry-bullet-color"></div>
<a class="icon-tag svg" ng-click="tagClicked(tag)">{{tag.text}}</a>
</li>
</ul>
</li>
<li>
<div class="app-navigation-entry-bullet bullet-color-red"></div>
<a ng-class="{selected: clickedNavigationItem=='strength_low'}" ng-click="filterCredentialBySpecial('strength_low')">{{ 'navigation.strength.bad' | translate }}</a>
</li>
<li>
<div class="app-navigation-entry-bullet bullet-color-yellow"></div>
<a ng-class="{selected: clickedNavigationItem=='strength_medium'}" ng-click="filterCredentialBySpecial('strength_medium')">{{ 'navigation.strength.medium' | translate }}</a>
</li>
<li>
<div class="app-navigation-entry-bullet bullet-color-green"></div>
<a ng-class="{selected: clickedNavigationItem=='strength_good'}" ng-click="filterCredentialBySpecial('strength_good')">{{ 'navigation.strength.good' | translate }}</a>
</li>
<li>
<a ng-class="{selected: clickedNavigationItem=='expired'}" class="icon-expired svg" ng-click="filterCredentialBySpecial('expired')">{{ 'navigation.expired' | translate }}</a>
</li>
<li data-id="trashbin" class="nav-trashbin pinned first-pinned">
<a ng-click="toggleDeleteTime()" ng-class="{'active': delete_time > 0}" class="icon-delete svg">
{{ 'deleted.credentials' | translate }}
</a>
</li>
</ul >
<ul class="with-icon hidden-list" ng-class="{ 'hidden-list': legacyNavbar }">
<li class="taginput">
<a class="taginput icon-search">
<tags-input id="tags-input-outer" ng-model="selectedTags" replace-spaces-with-dashes="false" ng-init="initPlaceholder()">
<auto-complete source="getTags($query)" min-length="0"></auto-complete>
</tags-input>
</a>
</li>
<li ng-repeat="tag in available_tags | orderBy:'text'" ng-if="selectedTags.indexOf(tag) == -1">
<a class="icon-tag svg" ng-click="tagClicked(tag)">{{tag.text}}</a>
</li>
<li data-id="trashbin" class="nav-trashbin pinned first-pinned">
<a ng-click="toggleDeleteTime()" ng-class="{'active': delete_time > 0}" class="icon-delete svg">
{{ 'deleted.credentials' | translate }}
</a>
</li>
</ul>
<div id="app-content">
<div id="app-content-wrapper">
<div id="content" ng-view="">
<div id="app-settings" ng-init="settingsShown = false;">
<div id="app-settings-header">
<button class="settings-button"
ng-click="settingsShown = !settingsShown"
>{{ 'settings' | translate }}
</button>
</div>
<div id="app-settings-content" class="hide-animation" ng-hide="!settingsShown">
</div>
</div>
</div>
<div class="settings-container-label">
<input class="checkbox" id="navbarLegacyMode" type="checkbox" ng-model="legacyNavbar">
<label for="navbarLegacyMode">{{'navigation.advanced.checkbox' | translate }}</label>
</div>
<div class="settings-container">
<a ng-href="#/vault/{{active_vault.guid}}/settings" class="link" ng-click="settingsShown = false;">
<button>{{ 'settings' | translate }}</button>
</a>
</div>
<div class="settings-container">
<button ng-click="logout()"><span class="link">{{'logout' | translate }}</span></button>
</div>
<div class="donation-container settings-container">
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6YS8F97PETVU2"
target="_blank" class="link" ng-click="settingsShown = false;">
<button class="donation-container">{{ 'donate' | translate }}</button>
</a>
</div>
<div class="settings-container">
<div ng-show="session_time_left">
<small>{{'session.time.left' | translate:translationData}}</small>
</div>
</div>
</div>
</div>
</div>
<div id="app-content" ng-class="{'vaultlist_sidebar_hidden': !selectedVault}">
<div id="app-content-wrapper">
<div id="content" ng-view="">
</div>
</div>
</div>
</div>

View file

@ -66,8 +66,9 @@ style('passman', 'app');
style('passman', 'public-page');
?>
<div ng-app="passmanApp" ng-controller="PublicSharedCredential">
<div class="row">
<div class="share-controller" ng-app="passmanApp" ng-controller="PublicSharedCredential">
<div class="share-container">
<div class="row">
<div class="col-xs-8 col-xs-push-2 col-xs-pull-2 credential_container">
<h2>Passman</h2>
<div ng-if="!shared_credential && !expired">
@ -204,4 +205,5 @@ style('passman', 'public-page');
</div>
</div>
</div>
</div>
</div>

View file

@ -1,21 +1,19 @@
<div id="controls">
<div class="actions creatable">
<div class="breadcrumb">
<div class="crumb svg ui-droppable">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg">
<a ng-click="cancelRevision()">{{active_vault.name}}</a>
</div>
<div class="crumb svg last">
<a ng-if="storedCredential.credential_id">{{ 'showing.revisions' | translate}} "{{revision.credential_data.label}}"</a>
<div class="main_list" off-click-filter="'.download-js-link, .sidebar-shown, #app-sidebar'">
<div id="passman-controls">
<div class="actions creatable">
<div class="breadcrumb">
<div class="crumb svg ui-droppable">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg">
<a ng-click="cancelRevision()">{{active_vault.name}}</a>
</div>
<div class="crumb svg last">
<a ng-if="storedCredential.credential_id">{{ 'showing.revisions' | translate}} "{{revision.credential_data.label}}"</a>
</div>
</div>
</div>
</div>
</div>
<div off-click="closeSelected()">
<table class="credential-table" ng-init="menuOpen = false;">
<tr ng-repeat="revision in revisions | orderBy:'-created'"
ng-click="selectRevision(revision)"
@ -31,9 +29,10 @@
<td>{{ 'no.revisions' | translate}}</td>
</tr>
</table>
</div>
<div id="app-sidebar" class="detailsView scroll-container app_sidebar"
ng-show="selectedRevision">
<div id="app-sidebar" class="detailsView scroll-container app_sidebar" off-click="closeSelected()"
ng-show="selectedRevision">
<span class="close icon-close" ng-click="closeSelected()"
alt="Close"></span>
<b ng-show="selectedRevision">{{ 'revision.of' | translate}} {{selectedRevision.created * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}</b>
@ -237,4 +236,4 @@
</div>
</div>
</div>

View file

@ -1,5 +1,6 @@
<div id="controls">
<div class="actions creatable">
<div id="passman-controls">
<div class="breadcrumb">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
@ -13,11 +14,13 @@
<a ng-if="!storedCredential.credential_id">{{ 'create.credential' | translate}}</a>
</div>
</div>
</div>
</div>
<div>
<ul class="tab_header">
<li ng-repeat="tab in tabs track by $index" class="tab"
ng-class="{active:isActiveTab(tab)}"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)" use-theme color="'true'"
>{{tab.title}}
<div class="indicator" use-theme negative="'true'"></div>
@ -29,3 +32,4 @@
<button ng-click="saveCredential()" ng-disabled="saving"><i class="fa fa-spinner fa-spin" ng-show="saving"></i> {{ 'save' | translate}}</button>
<button ng-click="cancel()">{{ 'cancel' | translate}}</button>
</div>
</div>

View file

@ -47,10 +47,14 @@
<div class="row" ng-show="credential.files.length > 0">
<div class="col-xs-4 col-md-3 col-lg-3">{{ 'files' | translate}}</div>
<div class="col-xs-8 col-md-9 col-lg-9"><div ng-repeat="file in credential.files"
class="link" ng-click="downloadFile(credential, file)">
{{file.filename}} ({{file.size | bytes}})
</div></div>
<div class="col-xs-8 col-md-9 col-lg-9">
<div ng-repeat="file in credential.files">
<a class="link" ng-click="downloadFile(credential, file)">
{{file.filename}} ({{file.size | bytes}})
</a>
<br>
</div>
</div>
</div>
<div class="row" ng-repeat="field in credential.custom_fields">

View file

@ -11,7 +11,7 @@
</select></label>
<div><b>{{selectedExporter.description}}</b></div>
<div ng-show="selectedExporter" class="col-xs-3 nopadding">
<div ng-show="selectedExporter" class="nopadding">
<label>{{ 'export.confirm.text' | translate }}</label>
<input type="password" ng-model="confirm_key">
<br />
@ -33,4 +33,4 @@
</div>
</div>
</div>
</div>
</div>

View file

@ -8,16 +8,16 @@
<div ng-controller="ImportCtrl" ng-show="!showGenericImport">
<div class="row">
<div class="col-xs-6">
<label>{{ 'import.type' | translate}}
<div class="import-selection">
<label>{{ 'import.type' | translate}}
<select ng-init="importerType" ng-model="importerType"
ng-change="setImporter(importerType)">
<option ng-repeat="importer in available_importers"
value="{{importer}}">
{{importer.name}}
</option>
</select>
</label>
</select></label>
</div>
<div ng-show="selectedImporter">
<b>{{ 'import.steps' | translate }}</b>
<ul class="import-steps">

View file

@ -1,5 +1,5 @@
<div class="password_settings">
<div class="col-xs-12 col-sm-5 col-lg-4">
<div class="col-xs-12 col-sm-5 col-lg-4 password-settings-padding-left-fix">
<label>
<span class="label">{{ 'password.generation.length' | translate}}</span><br />
<input type="number" ng-model="vault_settings.pwSettings.length" min="1">

View file

@ -28,15 +28,17 @@
<tr ng-repeat="result in scan_result | orderBy:'password_zxcvbn_result.score'">
<td>{{result.label}}</td>
<td class="score">
<ng-password-meter
password="result.password"></ng-password-meter>
<ng-password-meter password="result.password"></ng-password-meter>
</td>
<td>
<span credential-field value="result.password"
secret="'true'"></span>
<span credential-field value="result.password" secret="'true'"></span>
</td>
<td>
<a class="link" ng-href="#/vault/{{active_vault.guid}}/edit/{{result.guid}}" tooltip="{{ 'edit.credential' | translate}}"><i class="fa fa-edit"></i></a>
<div>
<a href="#/vault/{{ active_vault.guid }}/edit/{{result.guid}}" class="link">
<i class="fa fa-edit"></i>
</a>
</div>
</td>
</tr>
</tbody>

View file

@ -78,7 +78,7 @@
<i class="fa fa-user" ng-if="user.pending === false"></i>
<i class="fa fa-user-times" ng-if="user.pending === true"></i>
{{user.userId}}
<small ng-if="user.pending === true" class="pull-right col-xs-4">{{ 'pending' | translate}}</small>
<small ng-if="user.pending === true" class="pull-right pending">{{ 'pending' | translate}}</small>
</td>
<td><input type="checkbox" ng-click="setPermission(user.acl, default_permissions.permissions.READ)" ng-checked="hasPermission(user.acl, default_permissions.permissions.READ)"> </td>
<td><input type="checkbox" ng-click="setPermission(user.acl, default_permissions.permissions.WRITE)" ng-checked="hasPermission(user.acl, default_permissions.permissions.WRITE)"></td>

View file

@ -1,8 +1,5 @@
<div>
<div class="cell">
<credential-icon credential="credential"></credential-icon>
</div>
<div style="display: none" id="iconPicker" title="{{ 'pick.icon' | translate }}">
<div class="cell icon-category-auth"></div>
<div style="display: none" id="iconPicker" title="{{ 'pick.icon' | translate }}">
<div class="iconList">
<div ng-repeat="(groupName, icons) in iconGroups">
<h2 style="clear: both" id="{{groupName}}">{{groupName}}</h2>
@ -25,4 +22,3 @@
</div>
</div>
</div>
</div>

View file

@ -1,29 +1,30 @@
<div id="controls">
<div class="actions creatable">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" >
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg">
<a ng-click="cancel()">{{active_vault.name}}</a>
</div>
<div class="crumb svg last">
<a>{{ 'settings' | translate}}</a>
</div>
</div>
</div>
</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 color="'true'">{{tab.title}}
<div class="indicator" use-theme negative="'true'"></div>
</li>
</ul>
<div class="tab_container settings edit_credential">
<div ng-include="currentTab.url"></div>
<div id="passman-controls">
<div class="breadcrumb">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg">
<a ng-click="cancel()">{{active_vault.name}}</a>
</div>
<div class="crumb svg last">
<a>{{ 'settings' | translate}}</a>
</div>
</div>
</div>
</div>
<div>
<ul class="tab_header">
<li ng-repeat="tab in tabs track by $index" class="tab"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)" use-theme color="'true'">{{tab.title | translate}}
<div class="indicator" use-theme negative="'true'"></div>
</li>
</ul>
<div class="tab_container settings edit_credential" use-theme type="'border-top-color'">
<div ng-include="currentTab.url"></div>
</div>
</div>

View file

@ -1,4 +1,5 @@
<div id="controls">
<div class="main_list.share">
<div id="passman-controls">
<div class="actions creatable">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
@ -15,21 +16,19 @@
</div>
</div>
</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 color="'true'">{{tab.title}}
<div class="indicator" use-theme negative="'true'"></div>
</li>
</ul>
<div class="tab_container share_credential" ng-show="currentTab">
<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 color="'true'">{{tab.title | translate}}
<div class="indicator" use-theme negative="'true'"></div>
</li>
</ul>
<div class="tab_container share_credential" ng-show="currentTab">
<div ng-include="currentTab.url"></div>
<button ng-click="applyShare()" ng-disabled="share_settings.linkSharing.enabled === false && share_settings.credentialSharedWithUserAndGroup.length === 0">{{ 'share' | translate}}</button>
<button ng-click="cancel()">{{ 'cancel' | translate}}</button>
<button class="btn btn-danger" ng-disabled="!storedCredential.shared_key" ng-click="unshareCredential(storedCredential)">{{ 'unshare' | translate}}</button>
</div>
</div>

View file

@ -1,27 +1,22 @@
<div off-click="closeSelected()" off-click-filter="'.download-js-link, .sidebar-shown'">
<div class="main_list" off-click-filter="'.download-js-link, .sidebar-shown, #app-sidebar'">
<div id="passman-controls" ng-class="{ 'sidebar-shown': selectedCredential }">
<div class="breadcrumb">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg last" ng-click="clearState()">
<span>{{active_vault.name}}</span>
<div class="crumb svg" ng-click="clearState()">
<a>{{active_vault.name}}</a>
</div>
</div>
<div class="addCredential" ng-hide="delete_time>0">
<button ng-click="addCredential()">+</button>
</div>
</div>
<div class="actions creatable">
<span ng-click="addCredential()" class="button new">
<span >+</span></span>
</div>
<div class="title" credential-counter="filtered_credentials" vault="active_vault" delete-time="delete_time" filters="filterOptions"></div>
<!--<span class="title" ng-if="delete_time"><br />
{{ 'deleted.since' | translate }}:
<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 class="searchboxContainer" ng-init="filterOptionShown = false;" off-click="filterOptionShown = false;">
<input type="text" ng-model="filterOptions.filterText" class="searchbox" id="searchBox"
placeholder="{{'search.credential' | translate}}" select-on-click clear-btn ng-click="filterOptionShown = true;">
@ -29,6 +24,7 @@
<input type="checkbox" ng-model="filterOptions.useRegex"> {{ 'use.regex' | translate }}
</div>
</div>
<div class="viewModes">
<div class="view-mode" ng-class="{'active': view_mode === 'list' }"
ng-click="switchViewMode('list')"><i class="fa fa-list"></i></div>
@ -60,7 +56,7 @@
<i class="fa fa-share-alt" ng-if="credential.acl"></i>
<i class="fa fa-share-alt-square" ng-if="credential.shared_key"> </i>
</span>
<span class="label">{{ ::credential.label}}</span>
<a class="label">{{ ::credential.label}}</a>
</td>
@ -74,7 +70,17 @@
ng-click="selectCredential(credential)"
use-theme type="'border-color'">
<div class="credential_content">
<div class="label">{{ ::credential.label}}</div>
<div>
<span class="icon" ng-if="credential.url">
<credential-icon credential="credential"></credential-icon>
</span>
<span class="icon" ng-if="!credential.url">
<i class="fa fa-lock" ng-if="!credential.acl && !credential.shared_key"></i>
<i class="fa fa-share-alt" ng-if="credential.acl"></i>
<i class="fa fa-share-alt-square" ng-if="credential.shared_key"> </i>
</span>
<div class="label">{{ ::credential.label}}</div>
</div>
<div class="tags">
<div class="tag" ng-repeat="tag in credential.tags_raw">
{{ ::tag.text}}
@ -83,58 +89,108 @@
</div>
</li>
</ul>
</div>
<div id="app-sidebar" class="detailsView scroll-container app_sidebar"
ng-show="selectedCredential">
<h2>{{selectedCredential.label}}</h2>
<span class="close icon-close" ng-click="closeSelected()"
alt="Close"></span>
<div credential-template="selectedCredential">
</div>
<div ng-show="selectedCredential">
<div>
<button class="button"
ng-click="editCredential(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)">
<span class="fa fa-edit"></span> {{ 'edit' | translate}}
</button>
<button class="button"
ng-click="deleteCredential(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)">
<span class="fa fa-trash"></span> {{ 'delete' | translate}}
</button>
<button class="button"
ng-click="shareCredential(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && selectedCredential.acl === undefined &&
(settings.user_sharing_enabled === 1 || settings.user_sharing_enabled === '1' || settings.link_sharing_enabled === 1 || settings.link_sharing_enabled === '1')">
<span class="fa fa-share"></span> {{ 'share' | translate}}
</button>
<button class="button"
ng-click="getRevisions(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.HISTORY)">
<span class="fa fa-undo"></span> {{ 'revisions' | translate}}
</button>
<button class="button"
ng-if="selectedCredential.delete_time > 0"
ng-click="recoverCredential(selectedCredential) && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)">
<span class="fa fa-recycle"></span> {{'recover' | translate}}
</button>
<button class="button"
ng-if="selectedCredential.delete_time > 0"
ng-click="destroyCredential(selectedCredential)">
<span class="fa fa-bomb"></span> {{'destroy' | translate}}
</button>
<div ng-if="getListSizes().listsize_wout_deleted==0 && no_credentials_label.all && !show_spinner && selectedtags.length==0 && filterOptions.filterText==''" class="nopasswords" ng-hide="delete_time>0">
<b>{{'vault.hint.hello' | translate}}</b><br>
<div>{{'vault.hint.hello.add' | translate}}</div>
<div class="">
<button ng-click="addCredential()">+</button>
</div>
</div>
<!--nopassword-hint for missing tagresults -->
<div ng-if="getListSizes().listsize_wout_deleted==0 && no_credentials_label.all && !show_spinner && selectedtags.length>0" class="nopasswords" ng-hide="delete_time>0">
<div>{{ 'vault.hint.list.notags' | translate}}</div>
</div>
<!--nopassword-hint for missing searchresults -->
<div ng-if="getListSizes().listsize_wout_deleted==0 && no_credentials_label.all && !show_spinner && selectedtags.length==0 && filterOptions.filterText!=''" class="nopasswords" ng-hide="delete_time>0">
<div>{{ 'vault.hint.list.nosearch' | translate}} <b>'{{filterOptions.filterText}}'</b></div>
</div>
<!--nopassword-hint for good strength -->
<div class="nopasswords" ng-if="no_credentials_label.s_good" ng-hide="getListSizes().listsize_wout_deleted>0">
<div>{{ 'vault.hint.list.nogood' | translate}}</div>
</div>
<!--nopassword-hint for medium strength -->
<div class="nopasswords" ng-if="no_credentials_label.s_medium" ng-hide="getListSizes().listsize_wout_deleted>0">
<div>{{ 'vault.hint.list.nomedium' | translate}}</div>
</div>
<!--nopassword-hint for bad strength -->
<div class="nopasswords" ng-if="no_credentials_label.s_low" ng-hide="getListSizes().listsize_wout_deleted>0">
<div>{{ 'vault.hint.list.nobad' | translate}}</div>
</div>
<!--nopassword-hint for expired -->
<div class="nopasswords" ng-if="no_credentials_label.expired" ng-hide="getListSizes().listsize_wout_deleted>0">
<div>{{ 'vault.hint.list.noexpired' | translate}}</div>
</div>
<!--nopassword-hint for deleted -->
<div class="nopasswords" ng-if="getListSizes().listsize_deleted==0" ng-hide="delete_time==0">
<div>{{ 'vault.hint.list.nodeleted' | translate}}</div>
</div>
</div>
</div>
<div id="app-sidebar" class="app_sidebar" ng-show="selectedCredential" off-click="closeSelected()" >
<span class="close icon-close" ng-click="closeSelected()" alt="Close"></span>
<div class="sidebar">
<span class="icon sidebar-icon" ng-if="selectedCredential.url">
<credential-icon credential="selectedCredential"></credential-icon>
</span>
<span class="icon sidebar-icon" ng-if="!selectedCredential.url">
<credential-icon credential="selectedCredential"></credential-icon>
</span>
<h2 class="sidebar-label">{{selectedCredential.label}}</h2>
</div>
<div credential-template="selectedCredential"></div>
<div ng-show="selectedCredential">
<div>
<button class="button"
ng-click="editCredential(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)">
<span class="fa fa-edit"></span> {{ 'edit' | translate}}
</button>
<button class="button"
ng-click="deleteCredential(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)">
<span class="fa fa-trash"></span> {{ 'delete' | translate}}
</button>
<button class="button"
ng-click="shareCredential(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && selectedCredential.acl === undefined &&
(settings.user_sharing_enabled === 1 || settings.user_sharing_enabled === '1' || settings.link_sharing_enabled === 1 || settings.link_sharing_enabled === '1')">
<span class="fa fa-share"></span> {{ 'share' | translate}}
</button>
<button class="button"
ng-click="getRevisions(selectedCredential)"
ng-if="selectedCredential.delete_time == 0 && hasPermission(selectedCredential.acl.permissions, permissions.permissions.HISTORY)">
<span class="fa fa-undo"></span> {{ 'revisions' | translate}}
</button>
<button class="button"
ng-if="selectedCredential.delete_time > 0"
ng-click="recoverCredential(selectedCredential) && hasPermission(selectedCredential.acl.permissions, permissions.permissions.WRITE)">
<span class="fa fa-recycle"></span> {{'recover' | translate}}
</button>
<button class="button"
ng-if="selectedCredential.delete_time > 0"
ng-click="destroyCredential(selectedCredential)">
<span class="fa fa-bomb"></span> {{'destroy' | translate}}
</button>
</div>
</div>
</div>
<div class="share_popup" style="display: none">

View file

@ -24,7 +24,6 @@
<li ng-if="vaults.length === 0">{{ 'no.vaults' | translate}}
</li>
</ul>
</div>
</div>
@ -58,7 +57,7 @@
ng-click="createVault(vault_name, vault_key, vault_key2)" ng-disabled="vault_key_score.score < minimal_value_key_strength || vault_key !== vault_key2 || vault_key === ''">
{{ 'new.vault.create' | translate }}
</button>
<div class="button" ng-if="creating_keys" >
<div class="button" ng-if="creating_keys">
<span>
<i class="fa fa-spinner fa-spin"></i>
{{creating_keys}}
@ -67,7 +66,7 @@
<div class="button button-red" ng-click="clearState()">
{{ 'cancel' | translate}}
</div>
<div class="hidden">
<div class="template-hidden">
{{sharing_keys}}
</div>
</div>

View file

@ -1,12 +1,14 @@
describe('MenuCtrl', function() {
beforeEach(module('passmanApp'));
beforeEach(module('LocalStorageModule'));
beforeEach(module('mock.vaultService'));
var $controller;
var $scope;
beforeEach(inject(function(_$controller_){
beforeEach(inject(function(_$controller_, _VaultService_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
//$controller.VaultService= _VaultService_;
}));
beforeEach(inject(function($rootScope) {
$scope = $rootScope.$new();

View file

@ -730,9 +730,11 @@ var OC={
* After 7sec the first notification is gone, then we can show another one
* if necessary.
*/
_ajaxConnectionLostHandler: _.throttle(function() {
OC.Notification.showTemporary(t('core', 'Connection to server lost'));
}, 7 * 1000, {trailing: false}),
_ajaxConnectionLostHandler: function(underscore){
underscore.throttle(function() {
OC.Notification.showTemporary(t('core', 'Connection to server lost'));
}, 7 * 1000, {trailing: false});
},
/**
* Process ajax error, redirects to main page
@ -761,7 +763,7 @@ var OC={
// Connection lost (e.g. WiFi disconnected or server is down)
setTimeout(function() {
if (!self._userIsNavigatingAway && !self._reloadCalled) {
self._ajaxConnectionLostHandler();
self._ajaxConnectionLostHandler(_);
}
}, 100);
}

View file

@ -0,0 +1,17 @@
angular.module('mock.vaultService', []).
service('VaultService', function($q) {
var vaultService = {};
var settings = {};
vaultService.getVaultSetting = function (key, default_value) {
if (settings[key]) {
return $q.when(settings[key]);
} else {
return $q.when(default_value);
}
};
vaultService.setVaultSetting = function (key, value) {
settings[key]=value;
};
return vaultService;
});