First setup of vaults

This commit is contained in:
brantje 2016-09-10 23:30:17 +02:00
parent 6e25bddac9
commit 6c502f183c
23 changed files with 468 additions and 28 deletions

View file

@ -10,12 +10,12 @@ module.exports = function (grunt) {
quoteChar: '\'',
useStrict: true,
htmlmin: {
collapseBooleanAttributes: true,
collapseBooleanAttributes: false,
collapseWhitespace: true,
removeAttributeQuotes: false,
removeComments: true,
removeEmptyAttributes: false,
removeRedundantAttributes: true,
removeRedundantAttributes: false,
removeScriptTypeAttributes: false,
removeStyleLinkTypeAttributes: false
}
@ -43,7 +43,7 @@ module.exports = function (grunt) {
//@TODO JSHint, comile sass
watch: {
scripts: {
files: ['Gruntfile.js', 'views/*.html'],
files: ['Gruntfile.js', 'templates/views/*.html','sass/*','sass/partials/*'],
tasks: ['html2js','sass'],
options: {
spawn: false,

View file

@ -22,7 +22,7 @@ return [
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
//Vault
['name' => 'vault#index', 'url' => '/api/v1/vaults', 'verb' => 'GET'],
['name' => 'vault#listVaults', 'url' => '/api/v1/vaults', 'verb' => 'GET'],
['name' => 'vault#create', 'url' => '/api/v1/vaults', 'verb' => 'POST'],
['name' => 'vault#get', 'url' => '/api/v1/vaults/{vault_id}', 'verb' => 'GET'],
['name' => 'vault#update', 'url' => '/api/v1/vaults/{vault_id}', 'verb' => 'PATCH'],

View file

@ -17,8 +17,9 @@ use OCA\Passman\Credential;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Controller;
class CredentialController extends ApiController {
class CredentialController extends Controller {
private $userId;

View file

@ -13,12 +13,11 @@ namespace OCA\Passman\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\ApiController;
class VaultController extends ApiController {
private $userId;
public function __construct($AppName, IRequest $request, $UserId) {
@ -26,6 +25,40 @@ class VaultController extends ApiController {
$this->userId = $UserId;
}
/**
* @NoAdminRequired
*/
public function listVaults() {
$vaults = [
array(
'vault_id' => uniqid(),
'name' => 'Vault ' . rand(1, 20),
'created' => time(),
'last_access' => time()
),
array(
'id' => uniqid(),
'name' => 'Vault ' . rand(1, 20),
'created' => time(),
'last_access' => time()
),
array(
'id' => uniqid(),
'name' => 'Vault ' . rand(1, 20),
'created' => time(),
'last_access' => time()
),
array(
'id' => uniqid(),
'name' => 'Vault ' . rand(1, 20),
'created' => time(),
'last_access' => time()
)
];
return new JSONResponse($vaults);
}
/**
* @NoAdminRequired
*/

View file

@ -1,3 +1,57 @@
.button-geen {
background: #37ce02;
color: #fff; }
.button-geen:hover {
background: #3ad802;
color: #fff; }
.button-red {
background: #ce3702;
color: #fff; }
.button-red:hover {
background: #d83a02;
color: #fff; }
.vault_wrapper {
margin: 0 auto;
margin-top: 20px;
width: 100%;
max-width: 420px;
-webkit-border-radius: 5px;
border-radius: 5px;
background-clip: padding-box;
/* stops bg color from leaking outside the border: */
box-shadow: 0 1px 1px #777;
background: #eee;
display: block; }
.vault_wrapper .vaultlist {
z-index: 500; }
.vault_wrapper .vaultlist li, .vault_wrapper .vaultlist div, .vault_wrapper .vaultlist span, .vault_wrapper .vaultlist small {
cursor: pointer; }
.vault_wrapper .vaultlist small {
color: #8e8e8e; }
.vault_wrapper .vaultlist li.selected {
background-color: #0082c9 !important;
color: #ddd; }
.vault_wrapper .vaultlist li {
border-bottom: 1px solid #8e8e8e;
padding: 16px; }
.vault_wrapper .vaultlist li:hover {
background-color: #f7f7f7; }
.vault_wrapper .login_form {
padding: 16px; }
.vault_wrapper .login_form input[type="password"], .vault_wrapper .login_form input[type="text"] {
width: 100%;
-webkit-border-radius: 5px;
border-radius: 5px;
background-clip: padding-box;
/* stops bg color from leaking outside the border: */ }
.vault_wrapper .login_form .button_wrapper .button {
width: 45%;
display: inline-block; }
.vault_wrapper .login_form .button {
margin-top: 10px; }
/*# sourceMappingURL=app.css.map */

View file

@ -1,7 +1,7 @@
{
"version": 3,
"mappings": "",
"sources": [],
"mappings": "AAAA,YAAY;EACV,UAAU,EAAE,OAAO;EACnB,KAAK,EAAE,IAAI;;AAEb,kBAAkB;EAChB,UAAU,EAAE,OAAoB;EAChC,KAAK,EAAE,IAAI;;AAGb,WAAW;EACT,UAAU,EAAE,OAAO;EACnB,KAAK,EAAE,IAAI;;AAEb,iBAAiB;EACf,UAAU,EAAE,OAAoB;EAChC,KAAK,EAAE,IAAI;;ACdb,cAAc;EACZ,MAAM,EAAE,MAAM;EACd,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,KAAK;ECMhB,qBAAqB,EDLE,GAAG;ECM1B,aAAa,EDNU,GAAG;ECO1B,eAAe,EAAE,WAAW;EAAG,qDAAqD;EDNpF,UAAU,EAAE,cAAc;EAC1B,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,KAAK;EACd,yBAAU;IAER,OAAO,EAAE,GAAG;IACZ,4HAAiB;MACf,MAAM,EAAE,OAAO;IAEjB,+BAAK;MACH,KAAK,EAAE,OAAO;IAEhB,qCAAW;MACT,gBAAgB,EAAE,kBAAkB;MACpC,KAAK,EAAE,IAAI;IAEb,4BAAE;MACA,aAAa,EAAE,iBAAiB;MAChC,OAAO,EAAE,IAAI;IAEf,kCAAQ;MACN,gBAAgB,EAAE,OAAO;EAG7B,0BAAW;IACT,OAAO,EAAE,IAAI;IACb,gGAA0C;MACxC,KAAK,EAAE,IAAI;MCvBf,qBAAqB,EDwBM,GAAG;MCvB9B,aAAa,EDuBc,GAAG;MCtB9B,eAAe,EAAE,WAAW;MAAG,qDAAqD;IDyBhF,kDAAO;MACL,KAAK,EAAE,GAAG;MACV,OAAO,EAAE,YAAY;IAGzB,kCAAO;MACL,UAAU,EAAE,IAAI",
"sources": ["../sass/partials/button.scss","../sass/vaults.scss","../sass/mixins.scss"],
"names": [],
"file": "app.css"
}

View file

@ -21,9 +21,8 @@ angular
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
controllerAs: 'main'
templateUrl: 'views/vaults.html',
controller: 'VaultCtrl'
})
.otherwise({
redirectTo: '/'

View file

@ -8,10 +8,6 @@
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('MainCtrl', function () {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
});
.controller('MainCtrl', ['$scope', 'VaultService', function ($scope, VaultService) {
$scope.selectedVault = false;
}]);

View file

@ -0,0 +1,17 @@
'use strict';
/**
* @ngdoc function
* @name passmanApp.controller:MenuCtrl
* @description
* # MenuCtrl
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('MenuCtrl', function () {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
});

View file

@ -0,0 +1,34 @@
'use strict';
/**
* @ngdoc function
* @name passmanApp.controller:MainCtrl
* @description
* # MainCtrl
* Controller of the passmanApp
*/
angular.module('passmanApp')
.controller('VaultCtrl', ['$scope', 'VaultService', function ($scope, VaultService) {
VaultService.getVaults().then(function (vaults) {
$scope.vaults = vaults;
});
$scope.default_vault = false;
$scope.remember_vault_password = false;
$scope.list_selected_vault = false;
$scope.clearState = function () {
$scope.list_selected_vault = false;
$scope.creating_vault = false;
};
$scope.selectVault = function(vault){
$scope.list_selected_vault = vault;
}
$scope.newVault = function(){
$scope.creating_vault = true;
}
}]);

View file

@ -0,0 +1,42 @@
'use strict';
/**
* @ngdoc filter
* @name passmanApp.filter:propsFilter
* @function
* @description
* # propsFilter
* Filter in the passmanApp.
*/
angular.module('passmanApp')
.filter('propsFilter', function () {
return function (items, props) {
var out = [];
if (angular.isArray(items)) {
var keys = Object.keys(props);
items.forEach(function (item) {
var itemMatches = false;
for (var i = 0; i < keys.length; i++) {
var prop = keys[i];
var text = props[prop].toLowerCase();
if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
itemMatches = true;
break;
}
}
if (itemMatches) {
out.push(item);
}
});
} else {
// Let the output be the input untouched
out = items;
}
return out;
};
});

View file

@ -0,0 +1,13 @@
'use strict';
/**
* @ngdoc service
* @name passmanApp.VaultService
* @description
* # VaultService
* Service in the passmanApp.
*/
angular.module('passmanApp')
.service('CacheService', [function () {
// AngularJS will instantiate a singleton by calling "new" on this function
}]);

View file

@ -0,0 +1,13 @@
'use strict';
/**
* @ngdoc service
* @name passmanApp.CredentialService
* @description
* # CredentialService
* Service in the passmanApp.
*/
angular.module('passmanApp')
.service('CredentialService', function () {
// AngularJS will instantiate a singleton by calling "new" on this function
});

View file

@ -0,0 +1,28 @@
'use strict';
/**
* @ngdoc service
* @name passmanApp.VaultService
* @description
* # VaultService
* Service in the passmanApp.
*/
angular.module('passmanApp')
.service('VaultService', ['$http', 'CacheService', function ($http, CacheService) {
// AngularJS will instantiate a singleton by calling "new" on this function
return {
getVaults: function(){
var queryUrl = OC.generateUrl('apps/passman/api/v1/vaults');
return $http.get(queryUrl).then(function (response) {
if(response.data){
return response.data;
} else {
return response;
}
});
},
createVault: function (vault) {
}
}
}]);

View file

@ -1,7 +1,7 @@
angular.module('templates-main', ['views/main.html']);
angular.module('templates-main', ['views/vaults.html']);
angular.module('views/main.html', []).run(['$templateCache', function($templateCache) {
angular.module('views/vaults.html', []).run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('views/main.html',
'Hello world!');
$templateCache.put('views/vaults.html',
'<div class="vault_wrapper"><div class="vaults" ng-if="!list_selected_vault && !creating_vault"><div class="ui-select-container ui-select-bootstrap vaultlist"><ul><li ng-click="newVault()">+ Create a new vault</li><li ng-repeat="vault in vaults" ng-class="{\'selected\': vault == list_selected_vault }" ng-click="selectVault(vault)"><div><span class="ui-select-choices-row-inner"><div class="ng-binding ng-scope">{{vault.name}}</div><small class="ng-binding ng-scope">Created: {{vault.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}} | Last accessed: {{vault.last_access * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</small></span></div></li></ul></div></div><div ng-if="creating_vault"><div class="login_form">Please give your new vault a name.<div><input type="text"></div><div class="button_wrapper"><div class="button button-geen">Create vault</div><div class="button button-red" ng-click="clearState()">Cancel</div></div></div></div><div ng-if="list_selected_vault != false"><div class="vaultlist"><ul><li ng-click="clearState()">Go back to vaults</li></ul></div><div class="login_form">Please input the password for {{list_selected_vault.name}}<div><input type="password"></div><div><div><label><input type="checkbox" ng-model="default_vault"> Set this vault as default.</label></div><div><label><input type="checkbox" ng-model="remember_vault_password"> Login automatically to this vault.</label></div></div><div class="button button-geen">Decrypt vault</div></div></div></div>');
}]);

View file

@ -46,8 +46,8 @@ class Application extends App {
return [
'id' => $c->getAppName(),
'order' => 10,
'name' => $c->query(IL10N::class)->t('Password'),
'href' => $server->getURLGenerator()->linkToRoute('passman.PageController.index'),
'name' => $c->query(IL10N::class)->t('Passwords'),
'href' => $server->getURLGenerator()->linkToRoute('passman.page.index'),
'icon' => $server->getURLGenerator()->imagePath($c->getAppName(), 'app.svg'),
];
};

View file

@ -1,3 +1,6 @@
@import 'container';
@import 'mixins';
@import 'partials/button';
@import 'vaults';
@import 'menu';

63
sass/mixins.scss Normal file
View file

@ -0,0 +1,63 @@
@mixin clearfix() {
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
}
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
border-radius: $radius;
background-clip: padding-box; /* stops bg color from leaking outside the border: */
}
// Single side border-radius
@mixin border-top-radius($radius) {
-webkit-border-top-right-radius: $radius;
border-top-right-radius: $radius;
-webkit-border-top-left-radius: $radius;
border-top-left-radius: $radius;
background-clip: padding-box;
}
@mixin border-right-radius($radius) {
-webkit-border-bottom-right-radius: $radius;
border-bottom-right-radius: $radius;
-webkit-border-top-right-radius: $radius;
border-top-right-radius: $radius;
background-clip: padding-box;
}
@mixin border-bottom-radius($radius) {
-webkit-border-bottom-right-radius: $radius;
border-bottom-right-radius: $radius;
-webkit-border-bottom-left-radius: $radius;
border-bottom-left-radius: $radius;
background-clip: padding-box;
}
@mixin border-left-radius($radius) {
-webkit-border-bottom-left-radius: $radius;
border-bottom-left-radius: $radius;
-webkit-border-top-left-radius: $radius;
border-top-left-radius: $radius;
background-clip: padding-box;
}
@mixin opacity($opacity) {
opacity: $opacity;
$opacity-ie: $opacity * 100;
filter: alpha(opacity=$opacity-ie); //IE8
}
@mixin center-block {
display: block;
margin-left: auto;
margin-right: auto;
}
@mixin font-size($sizeValue: 12 ){
font-size: $sizeValue + px; //fallback for old browsers
font-size: (0.125 * $sizeValue) + rem;
}

17
sass/partials/button.scss Normal file
View file

@ -0,0 +1,17 @@
.button-geen{
background: #37ce02;
color: #fff;
}
.button-geen:hover{
background: lighten(#37ce02, 2%);
color: #fff;
}
.button-red{
background: #ce3702;
color: #fff;
}
.button-red:hover{
background: lighten(#ce3702, 2%);
color: #fff;
}

48
sass/vaults.scss Normal file
View file

@ -0,0 +1,48 @@
.vault_wrapper{
margin: 0 auto;
margin-top: 20px;
width: 100%;
max-width: 420px;
@include border-radius(5px);
box-shadow: 0 1px 1px #777;
background: #eee;
display: block;
.vaultlist{
z-index: 500;
li,div,span,small{
cursor: pointer;
}
small{
color: #8e8e8e;
}
li.selected{
background-color: #0082c9 !important;
color: #ddd;
}
li{
border-bottom: 1px solid #8e8e8e;
padding: 16px;
}
li:hover{
background-color: #f7f7f7;
}
}
.login_form{
padding: 16px;
input[type="password"], input[type="text"]{
width: 100%;
@include border-radius(5px);
}
.button_wrapper{
.button{
width: 45%;
display: inline-block;
}
}
.button{
margin-top: 10px;
}
}
}

View file

@ -14,6 +14,11 @@ script('passman', 'vendor/angular-touch/angular-touch.min');
script('passman', 'app/app');
script('passman', 'templates');
script('passman', 'app/controllers/main');
script('passman', 'app/controllers/vault');
script('passman', 'app/filters/propsfilter');
script('passman', 'app/services/cacheservice');
script('passman', 'app/services/vaultservice');
script('passman', 'app/services/credentialservice');
/*
@ -22,8 +27,8 @@ script('passman', 'app/controllers/main');
style('passman', 'app');
?>
<div id="app" ng-app="passmanApp">
<div id="app-navigation">
<div id="app" ng-app="passmanApp" ng-controller="MainCtrl">
<div id="app-navigation" ng-if="selectedVault">
<ul>
<li><a href="#">First level entry</a></li>
<li>

View file

@ -1 +0,0 @@
Hello world!

View file

@ -0,0 +1,75 @@
<div class="vault_wrapper">
<div class="vaults"
ng-if="!list_selected_vault && !creating_vault">
<div class="ui-select-container ui-select-bootstrap vaultlist">
<ul>
<li ng-click="newVault()">+ Create a new vault</li>
<li ng-repeat="vault in vaults"
ng-class="{'selected': vault == list_selected_vault }"
ng-click="selectVault(vault)">
<div>
<span class="ui-select-choices-row-inner">
<div class="ng-binding ng-scope">{{vault.name}}</div>
<small class="ng-binding ng-scope">
Created: {{vault.created * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
|
Last accessed: {{vault.last_access * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
</small>
</span>
</div>
</li>
</ul>
</div>
</div>
<div ng-if="creating_vault">
<div class="login_form">
Please give your new vault a name.
<div>
<input type="text">
</div>
<div class="button_wrapper">
<div class="button button-geen">
Create vault
</div>
<div class="button button-red" ng-click="clearState()">
Cancel
</div>
</div>
</div>
</div>
<div ng-if="list_selected_vault != false">
<div class="vaultlist">
<ul>
<li ng-click="clearState()">Go back to vaults</li>
</ul>
</div>
<div class="login_form">
Please input the password for {{list_selected_vault.name}}
<div>
<input type="password">
</div>
<div>
<div>
<label>
<input type="checkbox" ng-model="default_vault">
Set this vault as default.
</label>
</div>
<div>
<label>
<input type="checkbox" ng-model="remember_vault_password">
Login automatically to this vault.
</label>
</div>
</div>
<div class="button button-geen">
Decrypt vault
</div>
</div>
</div>
</div>