mirror of
https://github.com/nextcloud/passman.git
synced 2025-10-10 13:36:55 +08:00
Start with showing Credentials
This commit is contained in:
parent
6caf31a992
commit
dee5ecda55
21 changed files with 517 additions and 295 deletions
|
@ -110,9 +110,9 @@
|
||||||
</field>
|
</field>
|
||||||
<field>
|
<field>
|
||||||
<name>vault_id</name>
|
<name>vault_id</name>
|
||||||
<type>text</type>
|
<type>integer</type>
|
||||||
<notnull>true</notnull>
|
<notnull>true</notnull>
|
||||||
<length>64</length>
|
<length>8</length>
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
<field>
|
<field>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<description>A password manager for Nextcloud</description>
|
<description>A password manager for Nextcloud</description>
|
||||||
<licence>AGPL</licence>
|
<licence>AGPL</licence>
|
||||||
<author>Sander Brand</author>
|
<author>Sander Brand</author>
|
||||||
<version>1.0.2.3</version>
|
<version>1.0.2.4</version>
|
||||||
<namespace>Passman</namespace>
|
<namespace>Passman</namespace>
|
||||||
<category>other</category>
|
<category>other</category>
|
||||||
<website>https://github.com/nextcloud/passman/</website>
|
<website>https://github.com/nextcloud/passman/</website>
|
||||||
|
|
|
@ -20,10 +20,11 @@ use OCA\Passman\Service\CredentialService;
|
||||||
class CredentialController extends ApiController {
|
class CredentialController extends ApiController {
|
||||||
private $userId;
|
private $userId;
|
||||||
private $credentialService;
|
private $credentialService;
|
||||||
|
|
||||||
public function __construct($AppName,
|
public function __construct($AppName,
|
||||||
IRequest $request,
|
IRequest $request,
|
||||||
$UserId,
|
$UserId,
|
||||||
CredentialService $credentialService){
|
CredentialService $credentialService) {
|
||||||
parent::__construct($AppName, $request);
|
parent::__construct($AppName, $request);
|
||||||
$this->userId = $UserId;
|
$this->userId = $UserId;
|
||||||
$this->credentialService = $credentialService;
|
$this->credentialService = $credentialService;
|
||||||
|
@ -75,8 +76,33 @@ class CredentialController extends ApiController {
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
*/
|
*/
|
||||||
public function updateCredential($credential_id) {
|
public function updateCredential($changed, $created,
|
||||||
return;
|
$credential_id, $custom_fields, $delete_time,
|
||||||
|
$description, $email, $expire_time, $favicon, $files, $guid,
|
||||||
|
$hidden, $label, $otp, $password, $renew_interval,
|
||||||
|
$tags, $url, $username, $vault_id) {
|
||||||
|
$credential = array(
|
||||||
|
'credential_id' => $credential_id,
|
||||||
|
'guid' => $guid,
|
||||||
|
'user_id' => $this->userId,
|
||||||
|
'label' => $label,
|
||||||
|
'description' => $description,
|
||||||
|
'created' => $created,
|
||||||
|
'changed' => $changed,
|
||||||
|
'tags' => $tags,
|
||||||
|
'email' => $email,
|
||||||
|
'username' => $username,
|
||||||
|
'password' => $password,
|
||||||
|
'url' => $url,
|
||||||
|
'favicon' => $favicon,
|
||||||
|
'renew_interval' => $renew_interval,
|
||||||
|
'expire_time' => $expire_time,
|
||||||
|
'files' => $files,
|
||||||
|
'custom_fields' => $custom_fields,
|
||||||
|
'otp' => $otp,
|
||||||
|
);
|
||||||
|
$credential = $this->credentialService->updateCredential($credential);
|
||||||
|
return new JSONResponse($credential);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
257
css/app.css
257
css/app.css
|
@ -1,26 +1,3 @@
|
||||||
.actions.creatable {
|
|
||||||
padding-left: 10px; }
|
|
||||||
.actions.creatable .bubble {
|
|
||||||
position: relative;
|
|
||||||
width: 185px;
|
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
background-clip: padding-box;
|
|
||||||
/* stops bg color from leaking outside the border: */
|
|
||||||
box-shadow: 0 1px 10px rgba(50, 50, 50, 0.7); }
|
|
||||||
.actions.creatable .bubble ul li {
|
|
||||||
padding-left: 10px; }
|
|
||||||
.actions.creatable .bubble ul .menuitem {
|
|
||||||
font-size: 12px;
|
|
||||||
display: inline; }
|
|
||||||
.actions.creatable .bubble:after {
|
|
||||||
right: inherit;
|
|
||||||
left: 10px;
|
|
||||||
top: -19px; }
|
|
||||||
|
|
||||||
#app-content-wrapper {
|
|
||||||
min-height: 95%; }
|
|
||||||
|
|
||||||
.button-geen {
|
.button-geen {
|
||||||
background: #37ce02;
|
background: #37ce02;
|
||||||
color: #fff; }
|
color: #fff; }
|
||||||
|
@ -156,105 +133,147 @@
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
.vault_wrapper {
|
.vault_wrapper {
|
||||||
width: 90%; } }
|
width: 90%; } }
|
||||||
.credential-table {
|
#app-content {
|
||||||
width: 100%;
|
overflow-x: hidden; }
|
||||||
margin-top: 44px; }
|
#app-content #app-content-wrapper {
|
||||||
.credential-table tr:hover {
|
min-height: 95%; }
|
||||||
background-color: whitesmoke; }
|
#app-content #app-content-wrapper .actions.creatable {
|
||||||
.credential-table tr td {
|
padding-left: 10px; }
|
||||||
cursor: pointer;
|
#app-content #app-content-wrapper .actions.creatable .bubble {
|
||||||
padding: 5px;
|
position: relative;
|
||||||
border-bottom: 1px solid #eeeeee; }
|
width: 185px;
|
||||||
.credential-table tr td .label {
|
-webkit-border-radius: 5px;
|
||||||
float: left; }
|
border-radius: 5px;
|
||||||
.credential-table tr td .tags {
|
background-clip: padding-box;
|
||||||
float: right; }
|
/* stops bg color from leaking outside the border: */
|
||||||
.credential-table tr td .tags .tag {
|
box-shadow: 0 1px 10px rgba(50, 50, 50, 0.7); }
|
||||||
background-color: rgba(240, 240, 240, 0.9);
|
#app-content #app-content-wrapper .actions.creatable .bubble ul li {
|
||||||
padding: 4px;
|
padding-left: 10px; }
|
||||||
font-size: 11px; }
|
#app-content #app-content-wrapper .actions.creatable .bubble ul .menuitem {
|
||||||
.credential-table tr td .icon-more {
|
|
||||||
display: inline-block;
|
|
||||||
float: right;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-top: 1px;
|
|
||||||
opacity: 0.4;
|
|
||||||
height: 20px;
|
|
||||||
width: 32px;
|
|
||||||
cursor: pointer; }
|
|
||||||
.credential-table tr td .icon-more:hover {
|
|
||||||
opacity: 1; }
|
|
||||||
.credential-table tr td .popovermenu {
|
|
||||||
margin-top: 7px;
|
|
||||||
height: 100px;
|
|
||||||
width: 100px;
|
|
||||||
right: -2px !important;
|
|
||||||
box-shadow: 0 1px 10px rgba(50, 50, 50, 0.7); }
|
|
||||||
.credential-table tr td .popovermenu ul {
|
|
||||||
display: block;
|
|
||||||
width: 100px;
|
|
||||||
height: 75px; }
|
|
||||||
.credential-table tr td .popovermenu ul li {
|
|
||||||
padding: 0px; }
|
|
||||||
.credential-table tr td .popovermenu ul .menuitem {
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: inline; }
|
display: inline; }
|
||||||
.credential-table tr td .popovermenu .action {
|
#app-content #app-content-wrapper .actions.creatable .bubble:after {
|
||||||
padding: 10px;
|
right: inherit;
|
||||||
margin: -10px; }
|
left: 10px;
|
||||||
|
top: -19px; }
|
||||||
.edit_credential {
|
#app-content #app-content-wrapper .credential-table {
|
||||||
padding-top: 10px; }
|
width: 100%;
|
||||||
.edit_credential label {
|
margin-top: 44px; }
|
||||||
display: block; }
|
#app-content #app-content-wrapper .credential-table tr:hover {
|
||||||
.edit_credential input[type="text"], .edit_credential input[type="password"] {
|
background-color: whitesmoke; }
|
||||||
width: 100%; }
|
#app-content #app-content-wrapper .credential-table tr.selected {
|
||||||
.edit_credential .tags {
|
background-color: #f8f8f8; }
|
||||||
float: left; }
|
#app-content #app-content-wrapper .credential-table tr td {
|
||||||
.edit_credential .tags .tag {
|
cursor: pointer;
|
||||||
background-color: rgba(240, 240, 240, 0.9);
|
padding: 5px;
|
||||||
padding: 4px;
|
border-bottom: 1px solid #eeeeee; }
|
||||||
font-size: 11px; }
|
#app-content #app-content-wrapper .credential-table tr td .label {
|
||||||
.edit_credential .credential_textarea {
|
float: left; }
|
||||||
width: 100%;
|
#app-content #app-content-wrapper .credential-table tr td .tags {
|
||||||
height: 100px; }
|
float: right; }
|
||||||
.edit_credential .password_settings label {
|
#app-content #app-content-wrapper .credential-table tr td .tags .tag {
|
||||||
overflow: hidden; }
|
background-color: rgba(240, 240, 240, 0.9);
|
||||||
.edit_credential .password_settings label input[type="checkbox"] {
|
padding: 4px;
|
||||||
width: auto !important;
|
font-size: 11px; }
|
||||||
float: left; }
|
#app-content #app-content-wrapper .credential-table tr td .icon-more {
|
||||||
.edit_credential .password_settings label .label {
|
display: inline-block;
|
||||||
float: left; }
|
float: right;
|
||||||
.edit_credential .password_settings label .label.sm {
|
margin-left: 5px;
|
||||||
font-size: 12px; }
|
margin-top: 1px;
|
||||||
.edit_credential .custom_fields, .edit_credential .files {
|
opacity: 0.4;
|
||||||
margin-top: 10px; }
|
height: 20px;
|
||||||
.edit_credential .custom_fields table, .edit_credential .files table {
|
width: 32px;
|
||||||
width: 100%; }
|
|
||||||
.edit_credential .custom_fields table thead th, .edit_credential .files table thead th {
|
|
||||||
color: #fff; }
|
|
||||||
.edit_credential .custom_fields table thead th.field_actions, .edit_credential .files table thead th.field_actions {
|
|
||||||
width: 15%; }
|
|
||||||
.edit_credential .custom_fields table tr td.field_actions, .edit_credential .files table tr td.field_actions {
|
|
||||||
font-size: 13px;
|
|
||||||
width: 15%; }
|
|
||||||
.edit_credential .custom_fields table tr td.field_actions i, .edit_credential .files table tr td.field_actions i {
|
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
.edit_credential .custom_fields table tr td, .edit_credential .custom_fields table tr th, .edit_credential .files table tr td, .edit_credential .files table tr th {
|
#app-content #app-content-wrapper .credential-table tr td .icon-more:hover {
|
||||||
width: 20%;
|
opacity: 1; }
|
||||||
padding: 5px; }
|
#app-content #app-content-wrapper .credential-table tr td .popovermenu {
|
||||||
.edit_credential .custom_fields table tr td .editable-has-buttons.editable-input, .edit_credential .custom_fields table tr th .editable-has-buttons.editable-input, .edit_credential .files table tr td .editable-has-buttons.editable-input, .edit_credential .files table tr th .editable-has-buttons.editable-input {
|
margin-top: 25px;
|
||||||
width: 55%; }
|
height: 100px;
|
||||||
.edit_credential .custom_fields table tr td, .edit_credential .files table tr td {
|
width: 100px;
|
||||||
height: 50px;
|
right: -2px !important;
|
||||||
vertical-align: middle; }
|
box-shadow: 0 1px 10px rgba(50, 50, 50, 0.7); }
|
||||||
.edit_credential .file_tab .progress {
|
#app-content #app-content-wrapper .credential-table tr td .popovermenu ul {
|
||||||
margin-top: 10px;
|
display: block;
|
||||||
height: 10px; }
|
width: 100px;
|
||||||
.edit_credential .file_tab .progress .progress-bar {
|
height: 75px; }
|
||||||
height: 10px;
|
#app-content #app-content-wrapper .credential-table tr td .popovermenu ul li {
|
||||||
background-image: none;
|
padding: 0px; }
|
||||||
background-color: #0082c9; }
|
#app-content #app-content-wrapper .credential-table tr td .popovermenu ul .menuitem {
|
||||||
|
font-size: 12px;
|
||||||
|
display: inline; }
|
||||||
|
#app-content #app-content-wrapper .credential-table tr td .popovermenu .action {
|
||||||
|
padding: 10px;
|
||||||
|
margin: -10px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential {
|
||||||
|
padding-top: 10px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential label {
|
||||||
|
display: block; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential input[type="text"], #app-content #app-content-wrapper .edit_credential input[type="password"] {
|
||||||
|
width: 100%; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .tags {
|
||||||
|
float: left; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .tags .tag {
|
||||||
|
background-color: rgba(240, 240, 240, 0.9);
|
||||||
|
padding: 4px;
|
||||||
|
font-size: 11px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .credential_textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 100px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .password_settings label {
|
||||||
|
overflow: hidden; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .password_settings label input[type="checkbox"] {
|
||||||
|
width: auto !important;
|
||||||
|
float: left; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .password_settings label .label {
|
||||||
|
float: left; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .password_settings label .label.sm {
|
||||||
|
font-size: 12px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields, #app-content #app-content-wrapper .edit_credential .files {
|
||||||
|
margin-top: 10px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table, #app-content #app-content-wrapper .edit_credential .files table {
|
||||||
|
width: 100%; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table thead th, #app-content #app-content-wrapper .edit_credential .files table thead th {
|
||||||
|
color: #fff; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table thead th.field_actions, #app-content #app-content-wrapper .edit_credential .files table thead th.field_actions {
|
||||||
|
width: 15%; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table tr td.field_actions, #app-content #app-content-wrapper .edit_credential .files table tr td.field_actions {
|
||||||
|
font-size: 13px;
|
||||||
|
width: 15%; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table tr td.field_actions i, #app-content #app-content-wrapper .edit_credential .files table tr td.field_actions i {
|
||||||
|
cursor: pointer; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table tr td, #app-content #app-content-wrapper .edit_credential .custom_fields table tr th, #app-content #app-content-wrapper .edit_credential .files table tr td, #app-content #app-content-wrapper .edit_credential .files table tr th {
|
||||||
|
width: 20%;
|
||||||
|
padding: 5px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table tr td .editable-has-buttons.editable-input, #app-content #app-content-wrapper .edit_credential .custom_fields table tr th .editable-has-buttons.editable-input, #app-content #app-content-wrapper .edit_credential .files table tr td .editable-has-buttons.editable-input, #app-content #app-content-wrapper .edit_credential .files table tr th .editable-has-buttons.editable-input {
|
||||||
|
width: 55%; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .custom_fields table tr td, #app-content #app-content-wrapper .edit_credential .files table tr td {
|
||||||
|
height: 50px;
|
||||||
|
vertical-align: middle; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .file_tab .progress {
|
||||||
|
margin-top: 10px;
|
||||||
|
height: 10px; }
|
||||||
|
#app-content #app-content-wrapper .edit_credential .file_tab .progress .progress-bar {
|
||||||
|
height: 10px;
|
||||||
|
background-image: none;
|
||||||
|
background-color: #0082c9; }
|
||||||
|
#app-content #app-content-wrapper .view_pane {
|
||||||
|
-webkit-box-shadow: 0px -4px 3px rgba(150, 150, 150, 0.75);
|
||||||
|
-moz-box-shadow: 0px -4px 3px rgba(150, 150, 150, 0.75);
|
||||||
|
box-shadow: 0px -4px 3px rgba(150, 150, 150, 0.75);
|
||||||
|
padding-top: 10px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #eee;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: none;
|
||||||
|
overflow-y: auto; }
|
||||||
|
#app-content #app-content-wrapper .view_pane .row {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0; }
|
||||||
|
#app-content #app-content-wrapper .view_pane.item_selected {
|
||||||
|
height: 20%;
|
||||||
|
display: inline-block; }
|
||||||
|
|
||||||
.settings-container div {
|
.settings-container div {
|
||||||
padding-left: 15px; }
|
padding-left: 15px; }
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -31,6 +31,18 @@ angular.module('passmanApp')
|
||||||
$location.path('/vault/'+ $scope.active_vault.vault_id +'/new')
|
$location.path('/vault/'+ $scope.active_vault.vault_id +'/new')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.editCredential = function(credential){
|
||||||
|
var credential = angular.copy(credential);
|
||||||
|
SettingsService.setSetting('edit_credential',credential);
|
||||||
|
$location.path('/vault/'+ $scope.active_vault.vault_id +'/edit/'+ credential.credential_id)
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.selectedCredential = false;
|
||||||
|
$scope.selectCredential = function (credential) {
|
||||||
|
console.log(credential);
|
||||||
|
$scope.selectedCredential = credential
|
||||||
|
}
|
||||||
|
|
||||||
$rootScope.$on('logout', function () {
|
$rootScope.$on('logout', function () {
|
||||||
console.log('Logout received, clean up');
|
console.log('Logout received, clean up');
|
||||||
$scope.credentials = [];
|
$scope.credentials = [];
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Controller of the passmanApp
|
* Controller of the passmanApp
|
||||||
*/
|
*/
|
||||||
angular.module('passmanApp')
|
angular.module('passmanApp')
|
||||||
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService) {
|
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService) {
|
||||||
$scope.active_vault = VaultService.getActiveVault();
|
$scope.active_vault = VaultService.getActiveVault();
|
||||||
|
|
||||||
|
|
||||||
|
@ -143,6 +143,7 @@ angular.module('passmanApp')
|
||||||
};
|
};
|
||||||
FileService.uploadFile(_file).then(function (result) {
|
FileService.uploadFile(_file).then(function (result) {
|
||||||
delete result.file_data;
|
delete result.file_data;
|
||||||
|
result.filename = EncryptService.decryptString(result.filename);
|
||||||
$scope.storedCredential.files.push(result);
|
$scope.storedCredential.files.push(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -177,5 +178,27 @@ angular.module('passmanApp')
|
||||||
qrInfo[parsedQR[5]] = parsedQR[6];
|
qrInfo[parsedQR[5]] = parsedQR[6];
|
||||||
$scope.storedCredential.otp = qrInfo;
|
$scope.storedCredential.otp = qrInfo;
|
||||||
$scope.$apply()
|
$scope.$apply()
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.saveCredential = function () {
|
||||||
|
|
||||||
|
delete $scope.storedCredential.password_repeat;
|
||||||
|
if(!$scope.storedCredential.credential_id){
|
||||||
|
$scope.storedCredential.vault_id = $scope.active_vault.vault_id;
|
||||||
|
CredentialService.createCredential($scope.storedCredential).then(function (result) {
|
||||||
|
$location.path('/vault/' + $routeParams.vault_id);
|
||||||
|
//@TODO Show notification
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
CredentialService.updateCredential($scope.storedCredential).then(function (result) {
|
||||||
|
SettingsService.setSetting('edit_credential', null);
|
||||||
|
$location.path('/vault/' + $routeParams.vault_id);
|
||||||
|
//@TODO Show notification
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancel = function(){
|
||||||
|
$location.path('/vault/' + $routeParams.vault_id);
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
18
js/app/filters/decrypt.js
Normal file
18
js/app/filters/decrypt.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc filter
|
||||||
|
* @name passmanApp.filter:decrypt
|
||||||
|
* @function
|
||||||
|
* @description
|
||||||
|
* # decrypt
|
||||||
|
* Filter in the passmanApp.
|
||||||
|
*/
|
||||||
|
angular.module('passmanApp')
|
||||||
|
.filter('decrypt',['EncryptService', function (EncryptService) {
|
||||||
|
return function (input) {
|
||||||
|
if(input) {
|
||||||
|
return EncryptService.decryptString(input);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}]);
|
|
@ -24,28 +24,31 @@ angular.module('passmanApp')
|
||||||
'url': null,
|
'url': null,
|
||||||
'favicon': null,
|
'favicon': null,
|
||||||
'renew_interval': null,
|
'renew_interval': null,
|
||||||
'expire_time': null,
|
'expire_time': 0,
|
||||||
'delete_time': 0,
|
'delete_time': 0,
|
||||||
'files': [],
|
'files': [],
|
||||||
'custom_fields': [],
|
'custom_fields': [],
|
||||||
'otp': {},
|
'otp': {},
|
||||||
'hidden': false
|
'hidden': false
|
||||||
};
|
};
|
||||||
var _encryptedFields = ['description','username','password','files','custom_fields','otp'];
|
var _encryptedFields = ['description', 'username', 'password', 'files', 'custom_fields', 'otp', 'email', 'tags', 'url'];
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
newCredential: function () {
|
newCredential: function () {
|
||||||
return angular.copy(credential);
|
return angular.copy(credential);
|
||||||
},
|
},
|
||||||
createCredential: function (credential) {
|
createCredential: function (credential) {
|
||||||
for(var i = 0; i < _encryptedFields.length; i++){
|
var _credential = angular.copy(credential);
|
||||||
|
for (var i = 0; i < _encryptedFields.length; i++) {
|
||||||
var field = _encryptedFields[i];
|
var field = _encryptedFields[i];
|
||||||
var fieldValue = angular.copy(credential[field]);
|
var fieldValue = angular.copy(credential[field]);
|
||||||
credential[field] = EncryptService.encryptString(JSON.stringify(fieldValue));
|
_credential[field] = EncryptService.encryptString(JSON.stringify(fieldValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryUrl = OC.generateUrl('apps/passman/api/v2/credentials');
|
var queryUrl = OC.generateUrl('apps/passman/api/v2/credentials');
|
||||||
return $http.post(queryUrl, credential).then(function (response) {
|
return $http.post(queryUrl, _credential).then(function (response) {
|
||||||
if(response.data){
|
if (response.data) {
|
||||||
return response.data;
|
return response.data;
|
||||||
} else {
|
} else {
|
||||||
return response;
|
return response;
|
||||||
|
@ -53,15 +56,16 @@ angular.module('passmanApp')
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
updateCredential: function (credential) {
|
updateCredential: function (credential) {
|
||||||
for(var i = 0; i < _encryptedFields.length; i++){
|
var _credential = angular.copy(credential);
|
||||||
|
for (var i = 0; i < _encryptedFields.length; i++) {
|
||||||
var field = _encryptedFields[i];
|
var field = _encryptedFields[i];
|
||||||
var fieldValue = angular.copy(credential[field]);
|
var fieldValue = angular.copy(credential[field]);
|
||||||
credential[field] = EncryptService.encryptString(JSON.stringify(fieldValue));
|
_credential[field] = EncryptService.encryptString(JSON.stringify(fieldValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryUrl = OC.generateUrl('apps/passman/api/v2/credentials/'+ credential.credential_id);
|
var queryUrl = OC.generateUrl('apps/passman/api/v2/credentials/' + credential.credential_id);
|
||||||
return $http.post(queryUrl, credential).then(function (response) {
|
return $http.patch(queryUrl, _credential).then(function (response) {
|
||||||
if(response.data){
|
if (response.data) {
|
||||||
return response.data;
|
return response.data;
|
||||||
} else {
|
} else {
|
||||||
return response;
|
return response;
|
||||||
|
@ -69,7 +73,7 @@ angular.module('passmanApp')
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
encryptCredential: function (credential) {
|
encryptCredential: function (credential) {
|
||||||
for(var i = 0; i < _encryptedFields.length; i++){
|
for (var i = 0; i < _encryptedFields.length; i++) {
|
||||||
var field = _encryptedFields[i];
|
var field = _encryptedFields[i];
|
||||||
var fieldValue = angular.copy(credential[field]);
|
var fieldValue = angular.copy(credential[field]);
|
||||||
credential[field] = EncryptService.encryptString(JSON.stringify(fieldValue));
|
credential[field] = EncryptService.encryptString(JSON.stringify(fieldValue));
|
||||||
|
@ -77,7 +81,7 @@ angular.module('passmanApp')
|
||||||
return credential;
|
return credential;
|
||||||
},
|
},
|
||||||
decryptCredential: function (credential) {
|
decryptCredential: function (credential) {
|
||||||
for(var i = 0; i < _encryptedFields.length; i++){
|
for (var i = 0; i < _encryptedFields.length; i++) {
|
||||||
var field = _encryptedFields[i];
|
var field = _encryptedFields[i];
|
||||||
var fieldValue = angular.copy(credential[field]);
|
var fieldValue = angular.copy(credential[field]);
|
||||||
credential[field] = JSON.parse(EncryptService.decryptString(fieldValue));
|
credential[field] = JSON.parse(EncryptService.decryptString(fieldValue));
|
||||||
|
|
|
@ -13,6 +13,7 @@ angular.module('passmanApp')
|
||||||
uploadFile: function (file) {
|
uploadFile: function (file) {
|
||||||
var queryUrl = OC.generateUrl('apps/passman/api/v2/file');
|
var queryUrl = OC.generateUrl('apps/passman/api/v2/file');
|
||||||
var _file = angular.copy(file);
|
var _file = angular.copy(file);
|
||||||
|
_file.filename = EncryptService.encryptString(_file.filename);
|
||||||
var data = EncryptService.encryptString(angular.copy(file.data));
|
var data = EncryptService.encryptString(angular.copy(file.data));
|
||||||
_file.data = data;
|
_file.data = data;
|
||||||
return $http.post(queryUrl, _file).then(function (response) {
|
return $http.post(queryUrl, _file).then(function (response) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ angular.module('templates-main', ['views/edit_credential.html', 'views/partials/
|
||||||
angular.module('views/edit_credential.html', []).run(['$templateCache', function($templateCache) {
|
angular.module('views/edit_credential.html', []).run(['$templateCache', function($templateCache) {
|
||||||
'use strict';
|
'use strict';
|
||||||
$templateCache.put('views/edit_credential.html',
|
$templateCache.put('views/edit_credential.html',
|
||||||
'<ul class="tab_header"><li ng-repeat="tab in tabs track by $index" class="tab" ng-class="{active:isActiveTab(tab)}" ng-click="onClickTab(tab)">{{tab.title}}</li></ul><div class="tab_container edit_credential"><div ng-include="currentTab.url"></div></div><textarea>\n' +
|
'<ul class="tab_header"><li ng-repeat="tab in tabs track by $index" class="tab" ng-class="{active:isActiveTab(tab)}" ng-click="onClickTab(tab)">{{tab.title}}</li></ul><div class="tab_container edit_credential"><div ng-include="currentTab.url"></div></div><button ng-click="saveCredential()">Save</button> <button ng-click="cancel()">Cancel</button><textarea>\n' +
|
||||||
'{{storedCredential}}\n' +
|
'{{storedCredential}}\n' +
|
||||||
' </textarea>');
|
' </textarea>');
|
||||||
}]);
|
}]);
|
||||||
|
@ -11,7 +11,7 @@ angular.module('views/edit_credential.html', []).run(['$templateCache', function
|
||||||
angular.module('views/partials/forms/edit_credential/basics.html', []).run(['$templateCache', function($templateCache) {
|
angular.module('views/partials/forms/edit_credential/basics.html', []).run(['$templateCache', function($templateCache) {
|
||||||
'use strict';
|
'use strict';
|
||||||
$templateCache.put('views/partials/forms/edit_credential/basics.html',
|
$templateCache.put('views/partials/forms/edit_credential/basics.html',
|
||||||
'<div class="row"><div class="col-xs-12 col-md-6"><label>Label</label><div><input type="text" ng-model="storedCredential.label"></div><label>Usermame</label><div><input type="text" ng-model="storedCredential.username"></div><label>E-mail</label><div><input type="text" ng-model="storedCredential.email"></div><label>Password</label><div><password-gen ng-model="storedCredential.password" settings="pwSettings" callback="pwGenerated"></password-gen><ng-password-meter password="storedCredential.password"></ng-password-meter></div><div><label>Repeat password</label><input type="password" ng-model="storedCredential.password_repeat"></div><label>URL</label><div><input type="text" ng-model="storedCredential.url"></div></div><div class="col-xs-12 col-md-6"><label>Description</label><div><textarea class="credential_textarea"></textarea></div><label>Add Tag</label><div><input type="text" placeholder="Add a tag"></div><label>Tags</label><div><div class="tags"><div class="tag">test</div></div></div></div></div>');
|
'<div class="row"><div class="col-xs-12 col-md-6"><label>Label</label><div><input type="text" ng-model="storedCredential.label"></div><label>Usermame</label><div><input type="text" ng-model="storedCredential.username"></div><label>E-mail</label><div><input type="text" ng-model="storedCredential.email"></div><label>Password</label><div><password-gen ng-model="storedCredential.password" settings="pwSettings" callback="pwGenerated"></password-gen><ng-password-meter password="storedCredential.password"></ng-password-meter></div><div><label>Repeat password</label><input type="password" ng-model="storedCredential.password_repeat"></div><label>URL</label><div><input type="text" ng-model="storedCredential.url"></div></div><div class="col-xs-12 col-md-6"><label>Description</label><div><textarea class="credential_textarea" ng-model="storedCredential.description"></textarea></div><label>Add Tag</label><div><input type="text" placeholder="Add a tag"></div><label>Tags</label><div><div class="tags"><div class="tag">test</div></div></div></div></div>');
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
angular.module('views/partials/forms/edit_credential/custom_fields.html', []).run(['$templateCache', function($templateCache) {
|
angular.module('views/partials/forms/edit_credential/custom_fields.html', []).run(['$templateCache', function($templateCache) {
|
||||||
|
@ -47,7 +47,7 @@ angular.module('views/partials/password-meter.html', []).run(['$templateCache',
|
||||||
angular.module('views/show_vault.html', []).run(['$templateCache', function($templateCache) {
|
angular.module('views/show_vault.html', []).run(['$templateCache', function($templateCache) {
|
||||||
'use strict';
|
'use strict';
|
||||||
$templateCache.put('views/show_vault.html',
|
$templateCache.put('views/show_vault.html',
|
||||||
'<div id="controls"><div class="breadcrumb"></div><div class="actions creatable"><span ng-click="menuOpen = !menuOpen" class="button new" ng-init="menuOpen = false" off-click="menuOpen = false;"><span>New</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li><span ng-click="addCredential()" class="menuitem action"><span class="icon icon-rename"></span> <span>New credential</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-shared"></span> <span>New shared credential</span></span></li></ul></div></div></div><table class="credential-table" ng-init="menuOpen = false"><tr ng-repeat="credential in credentials"><td><span class="label">{{credential.label}}</span> <span class="icon icon-more" ng-click="menuOpen = !menuOpen" off-click="menuOpen = false;"></span> <span class="tags"><span class="tag">Tag 1</span> <span class="tag">Tag 2</span> <span class="tag">Tag 4</span> <span class="tag">Tag 4</span> <span class="tag">Long tag xD</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li><span class="menuitem action"><span class="icon icon-rename"></span><span>Edit</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-share"></span><span>Share</span></span></li><li><span class="menuitem action" data-action="Delete"><span class="icon icon-delete"></span><span>Delete</span></span></li></ul></div></td></tr></table>');
|
'<div id="controls"><div class="breadcrumb"></div><div class="actions creatable"><span ng-click="menuOpen = !menuOpen" class="button new" ng-init="menuOpen = false" off-click="menuOpen = false;"><span>New</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li><span ng-click="addCredential()" class="menuitem action"><span class="icon icon-rename"></span> <span>New credential</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-shared"></span> <span>New shared credential</span></span></li></ul></div></div></div><table class="credential-table" ng-init="menuOpen = false;"><tr ng-repeat="credential in credentials" ng-if="credential.hidden == 0 && credential.delete_time == 0" ng-click="selectCredential(credential)" ng-class="{\'selected\': selectedCredential.credential_id == credential.credential_id}"><td><span class="label">{{credential.label}}</span> <span class="icon icon-more" ng-click="menuOpen = !menuOpen" off-click="menuOpen = false;"></span> <span class="tags"><span class="tag">Tag 1</span> <span class="tag">Tag 2</span> <span class="tag">Tag 4</span> <span class="tag">Tag 4</span> <span class="tag">Long tag xD</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li ng-click="editCredential(credential)"><span class="menuitem action"><span class="icon icon-rename"></span><span>Edit</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-share"></span><span>Share</span></span></li><li><span class="menuitem action" data-action="Delete"><span class="icon icon-delete"></span><span>Delete</span></span></li></ul></div></td></tr></table><div class="view_pane" ng-class="{\'item_selected\': selectedCredential}"><div class="row"><div class="col-xs-2 col-sm-2 col-md-1">Label</div><div class="col-xs-6 col-sm-4 col-md-4">{{selectedCredential.label}}</div></div><div class="row"><div class="col-xs-2 col-sm-2 col-md-1">Account</div><div class="col-xs-6 col-sm-4 col-md-4">{{selectedCredential.label}}</div></div><div class="row"><div class="col-xs-2 col-sm-2 col-md-1">Password</div><div class="col-xs-6 col-sm-4 col-md-4">{{selectedCredential.label}}</div></div><div class="row"><div class="col-xs-2 col-sm-2 col-md-1">Files</div><div class="col-xs-6 col-sm-4 col-md-4">{{selectedCredential.label}}</div></div><div class="row"><div class="col-xs-2 col-sm-2 col-md-1">Custom fields</div><div class="col-xs-6 col-sm-4 col-md-4">{{selectedCredential.label}}</div></div><div class="row"><div class="col-xs-2 col-sm-2 col-md-1">Changed</div><div class="col-xs-6 col-sm-4 col-md-4">{{selectedCredential.label}}</div></div><div class="row"><div class="col-xs-2 col-sm-2 col-md-1">Created</div><div class="col-xs-6 col-sm-4 col-md-4">{{selectedCredential.label}}</div></div></div>');
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
angular.module('views/vaults.html', []).run(['$templateCache', function($templateCache) {
|
angular.module('views/vaults.html', []).run(['$templateCache', function($templateCache) {
|
||||||
|
|
|
@ -93,6 +93,8 @@ class Credential extends Entity implements \JsonSerializable{
|
||||||
$this->addType('renewInterval', 'integer');
|
$this->addType('renewInterval', 'integer');
|
||||||
$this->addType('expireTime', 'integer');
|
$this->addType('expireTime', 'integer');
|
||||||
$this->addType('deleteTime', 'integer');
|
$this->addType('deleteTime', 'integer');
|
||||||
|
$this->addType('vault_id', 'integer');
|
||||||
|
$this->addType('credential_id', 'integer');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,4 +58,26 @@ class CredentialMapper extends Mapper {
|
||||||
return parent::insert($credential);
|
return parent::insert($credential);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function update($raw_credential){
|
||||||
|
$credential = new Credential();
|
||||||
|
$credential->setId($raw_credential['credential_id']);
|
||||||
|
$credential->setUserId($raw_credential['user_id']);
|
||||||
|
$credential->setLabel($raw_credential['label']);
|
||||||
|
$credential->setDescription($raw_credential['description']);
|
||||||
|
$credential->setChanged($this->utils->getTime());
|
||||||
|
$credential->setTags($raw_credential['tags']);
|
||||||
|
$credential->setEmail($raw_credential['email']);
|
||||||
|
$credential->setUsername($raw_credential['username']);
|
||||||
|
$credential->setPassword($raw_credential['password']);
|
||||||
|
$credential->setUrl($raw_credential['url']);
|
||||||
|
$credential->setFavicon($raw_credential['favicon']);
|
||||||
|
$credential->setRenewInterval($raw_credential['renew_interval']);
|
||||||
|
$credential->setExpireTime($raw_credential['expire_time']);
|
||||||
|
$credential->setFiles($raw_credential['files']);
|
||||||
|
$credential->setCustomFields($raw_credential['custom_fields']);
|
||||||
|
$credential->setOtp($raw_credential['otp']);
|
||||||
|
$credential->setHidden($raw_credential['hidden']);
|
||||||
|
return parent::update($credential);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,6 +29,10 @@ class CredentialService {
|
||||||
return $this->credentialMapper->create($credential);
|
return $this->credentialMapper->create($credential);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updateCredential($credential) {
|
||||||
|
return $this->credentialMapper->update($credential);
|
||||||
|
}
|
||||||
|
|
||||||
public function getCredentialsByVaultId($vault_id, $user_id){
|
public function getCredentialsByVaultId($vault_id, $user_id){
|
||||||
return $this->credentialMapper->getCredentialsByVaultId($vault_id, $user_id);
|
return $this->credentialMapper->getCredentialsByVaultId($vault_id, $user_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
@import 'variables';
|
@import 'variables';
|
||||||
@import 'mixins';
|
@import 'mixins';
|
||||||
@import 'container';
|
|
||||||
@import 'partials/button';
|
@import 'partials/button';
|
||||||
@import 'partials/popovermenu';
|
@import 'partials/popovermenu';
|
||||||
@import 'partials/tabs';
|
@import 'partials/tabs';
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
.actions.creatable{
|
|
||||||
padding-left: 10px;
|
|
||||||
.bubble{
|
|
||||||
position: relative;
|
|
||||||
width: 185px;
|
|
||||||
@include border-radius(5px);
|
|
||||||
box-shadow: 0 1px 10px rgba(50, 50, 50, .7);
|
|
||||||
ul{
|
|
||||||
li{
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
.menuitem{
|
|
||||||
font-size: 12px;
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.bubble:after{
|
|
||||||
right: inherit;
|
|
||||||
left: 10px;
|
|
||||||
top: -19px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#app-content-wrapper{
|
|
||||||
min-height: 95%;
|
|
||||||
}
|
|
|
@ -1,143 +1,196 @@
|
||||||
.credential-table {
|
#app-content {
|
||||||
width: 100%;
|
overflow-x: hidden;
|
||||||
margin-top: 44px;
|
#app-content-wrapper {
|
||||||
tr:hover {
|
min-height: 95%;
|
||||||
background-color: darken(#fff, 4%);
|
.actions.creatable {
|
||||||
}
|
padding-left: 10px;
|
||||||
tr {
|
.bubble {
|
||||||
td {
|
position: relative;
|
||||||
cursor: pointer;
|
width: 185px;
|
||||||
padding: 5px;
|
@include border-radius(5px);
|
||||||
border-bottom: 1px solid #eeeeee;
|
|
||||||
.label {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.tags {
|
|
||||||
float: right;
|
|
||||||
.tag {
|
|
||||||
background-color: rgba(240, 240, 240, .9);
|
|
||||||
padding: 4px;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.icon-more {
|
|
||||||
display: inline-block;
|
|
||||||
float: right;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-top: 1px;
|
|
||||||
opacity: 0.4;
|
|
||||||
height: 20px;
|
|
||||||
width: 32px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.icon-more:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.popovermenu {
|
|
||||||
margin-top: 7px;
|
|
||||||
height: 100px;
|
|
||||||
width: 100px;
|
|
||||||
right: -2px !important;
|
|
||||||
box-shadow: 0 1px 10px rgba(50, 50, 50, .7);
|
box-shadow: 0 1px 10px rgba(50, 50, 50, .7);
|
||||||
ul {
|
ul {
|
||||||
display: block;
|
|
||||||
width: 100px;
|
|
||||||
height: 75px;
|
|
||||||
li {
|
li {
|
||||||
padding: 0px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
.menuitem {
|
.menuitem {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.action {
|
}
|
||||||
padding: 10px;
|
.bubble:after {
|
||||||
margin: -10px;
|
right: inherit;
|
||||||
}
|
left: 10px;
|
||||||
|
top: -19px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.credential-table {
|
||||||
}
|
|
||||||
|
|
||||||
.edit_credential {
|
|
||||||
padding-top: 10px;
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
input[type="text"], input[type="password"] {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.tags {
|
|
||||||
float: left;
|
|
||||||
.tag {
|
|
||||||
background-color: rgba(240, 240, 240, .9);
|
|
||||||
padding: 4px;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.credential_textarea {
|
|
||||||
width: 100%;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
.password_settings {
|
|
||||||
label {
|
|
||||||
overflow: hidden;
|
|
||||||
input[type="checkbox"] {
|
|
||||||
width: auto !important;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.label {
|
|
||||||
&.sm{
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.custom_fields, .files {
|
|
||||||
margin-top: 10px;
|
|
||||||
table {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
thead {
|
margin-top: 44px;
|
||||||
th {
|
tr:hover {
|
||||||
color: #fff;
|
background-color: darken(#fff, 4%);
|
||||||
}
|
|
||||||
th.field_actions {
|
|
||||||
width: 15%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
td.field_actions {
|
&.selected {
|
||||||
font-size: 13px;
|
background-color: #f8f8f8;
|
||||||
width: 15%;
|
}
|
||||||
i{
|
td {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
border-bottom: 1px solid #eeeeee;
|
||||||
|
.label {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.tags {
|
||||||
|
float: right;
|
||||||
|
.tag {
|
||||||
|
background-color: rgba(240, 240, 240, .9);
|
||||||
|
padding: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.icon-more {
|
||||||
|
display: inline-block;
|
||||||
|
float: right;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 1px;
|
||||||
|
opacity: 0.4;
|
||||||
|
height: 20px;
|
||||||
|
width: 32px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
.icon-more:hover {
|
||||||
td, th {
|
opacity: 1;
|
||||||
width: 20%;
|
}
|
||||||
padding: 5px;
|
.popovermenu {
|
||||||
.editable-has-buttons.editable-input {
|
margin-top: 25px;
|
||||||
width: 55%;
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
right: -2px !important;
|
||||||
|
box-shadow: 0 1px 10px rgba(50, 50, 50, .7);
|
||||||
|
ul {
|
||||||
|
display: block;
|
||||||
|
width: 100px;
|
||||||
|
height: 75px;
|
||||||
|
li {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
.menuitem {
|
||||||
|
font-size: 12px;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.action {
|
||||||
|
padding: 10px;
|
||||||
|
margin: -10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
td{
|
|
||||||
height: 50px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.file_tab{
|
.edit_credential {
|
||||||
.progress{
|
padding-top: 10px;
|
||||||
margin-top: 10px;
|
label {
|
||||||
height: 10px;
|
display: block;
|
||||||
.progress-bar{
|
|
||||||
height: 10px;
|
|
||||||
background-image: none;
|
|
||||||
background-color: #0082c9;
|
|
||||||
}
|
}
|
||||||
|
input[type="text"], input[type="password"] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.tags {
|
||||||
|
float: left;
|
||||||
|
.tag {
|
||||||
|
background-color: rgba(240, 240, 240, .9);
|
||||||
|
padding: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.credential_textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.password_settings {
|
||||||
|
label {
|
||||||
|
overflow: hidden;
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: auto !important;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
&.sm {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.custom_fields, .files {
|
||||||
|
margin-top: 10px;
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
thead {
|
||||||
|
th {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
th.field_actions {
|
||||||
|
width: 15%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tr {
|
||||||
|
td.field_actions {
|
||||||
|
font-size: 13px;
|
||||||
|
width: 15%;
|
||||||
|
i {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
td, th {
|
||||||
|
width: 20%;
|
||||||
|
padding: 5px;
|
||||||
|
.editable-has-buttons.editable-input {
|
||||||
|
width: 55%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
height: 50px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.file_tab {
|
||||||
|
.progress {
|
||||||
|
margin-top: 10px;
|
||||||
|
height: 10px;
|
||||||
|
.progress-bar {
|
||||||
|
height: 10px;
|
||||||
|
background-image: none;
|
||||||
|
background-color: #0082c9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.view_pane {
|
||||||
|
-webkit-box-shadow: 0px -4px 3px rgba(150, 150, 150, 0.75);
|
||||||
|
-moz-box-shadow: 0px -4px 3px rgba(150, 150, 150, 0.75);
|
||||||
|
box-shadow: 0px -4px 3px rgba(150, 150, 150, 0.75);
|
||||||
|
padding-top: 10px;
|
||||||
|
.row {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
&.item_selected {
|
||||||
|
height: 20%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #eee;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: none;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,6 +30,7 @@ script('passman', 'app/controllers/credential');
|
||||||
script('passman', 'app/controllers/edit_credential');
|
script('passman', 'app/controllers/edit_credential');
|
||||||
script('passman', 'app/filters/range');
|
script('passman', 'app/filters/range');
|
||||||
script('passman', 'app/filters/propsfilter');
|
script('passman', 'app/filters/propsfilter');
|
||||||
|
script('passman', 'app/filters/decrypt');
|
||||||
script('passman', 'app/services/cacheservice');
|
script('passman', 'app/services/cacheservice');
|
||||||
script('passman', 'app/services/vaultservice');
|
script('passman', 'app/services/vaultservice');
|
||||||
script('passman', 'app/services/credentialservice');
|
script('passman', 'app/services/credentialservice');
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
<div class="tab_container edit_credential">
|
<div class="tab_container edit_credential">
|
||||||
<div ng-include="currentTab.url"></div>
|
<div ng-include="currentTab.url"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<button ng-click="saveCredential()">Save</button>
|
||||||
|
<button ng-click="cancel()">Cancel</button>
|
||||||
<textarea>
|
<textarea>
|
||||||
{{storedCredential}}
|
{{storedCredential}}
|
||||||
</textarea>
|
</textarea>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<div class="col-xs-12 col-md-6">
|
<div class="col-xs-12 col-md-6">
|
||||||
<label>Description</label>
|
<label>Description</label>
|
||||||
<div>
|
<div>
|
||||||
<textarea class="credential_textarea"></textarea>
|
<textarea class="credential_textarea" ng-model="storedCredential.description"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<label>Add Tag</label>
|
<label>Add Tag</label>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="credential-table" ng-init="menuOpen = false">
|
<table class="credential-table" ng-init="menuOpen = false;">
|
||||||
<tr ng-repeat="credential in credentials">
|
<tr ng-repeat="credential in credentials" ng-if="credential.hidden == 0 && credential.delete_time == 0" ng-click="selectCredential(credential)" ng-class="{'selected': selectedCredential.credential_id == credential.credential_id}">
|
||||||
<td>
|
<td>
|
||||||
<span class="label">{{credential.label}}</span>
|
<span class="label">{{credential.label}}</span>
|
||||||
<span class="icon icon-more" ng-click="menuOpen = !menuOpen"
|
<span class="icon icon-more" ng-click="menuOpen = !menuOpen"
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
</span>
|
</span>
|
||||||
<div class="actionList popovermenu bubble menu" ng-show="menuOpen">
|
<div class="actionList popovermenu bubble menu" ng-show="menuOpen">
|
||||||
<ul>
|
<ul>
|
||||||
<li><span
|
<li ng-click="editCredential(credential)"><span
|
||||||
class="menuitem action"
|
class="menuitem action"
|
||||||
><span
|
><span
|
||||||
class="icon icon-rename"></span><span>Edit</span></span>
|
class="icon icon-rename"></span><span>Edit</span></span>
|
||||||
|
@ -64,3 +64,65 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<div class="view_pane" ng-class="{'item_selected': selectedCredential}" >
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||||
|
Label
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-4 col-md-4">
|
||||||
|
{{selectedCredential.label}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||||
|
Account
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-4 col-md-4">
|
||||||
|
{{selectedCredential.label}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||||
|
Password
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-4 col-md-4">
|
||||||
|
{{selectedCredential.label}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||||
|
Files
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-4 col-md-4">
|
||||||
|
{{selectedCredential.label}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||||
|
Custom fields
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-4 col-md-4">
|
||||||
|
{{selectedCredential.label}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||||
|
Changed
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-4 col-md-4">
|
||||||
|
{{selectedCredential.label}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||||
|
Created
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-4 col-md-4">
|
||||||
|
{{selectedCredential.label}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
Loading…
Add table
Reference in a new issue