simple password generator

pull/8/head
Antelle 2015-10-20 00:24:32 +03:00
parent 7e1b075c5e
commit ee4f770952
8 changed files with 257 additions and 26 deletions

View File

@ -4,7 +4,10 @@ var Backbone = require('backbone');
var AppSettingsModel = Backbone.Model.extend({
defaults: {
theme: 'd'
theme: 'd',
genOpts: {
length: 16, upper: true, lower: true, digits: true, special: false, brackets: false, high: false, ambiguous: false
}
},
initialize: function() {

View File

@ -0,0 +1,37 @@
'use strict';
var kdbxweb = require('kdbxweb');
var PasswordGenerator = {
charRanges: {
upper: 'ABCDEFGHJKLMNPQRSTUVWXYZ',
lower: 'abcdefghijkmnpqrstuvwxyz',
digits: '23456789',
special: '!@#$%^&*_+-=,./?;:`"~\'\\',
brackets: '()[]<>',
high: '¡¢£¤¥¦§©ª«¬®¯°±²³´µ¶¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ',
ambiguous: 'O0oIl1'
},
generate: function(opts) {
if (!opts || typeof opts.length !== 'number' || opts.length < 0) {
return '';
}
var pass = '';
var ranges = Object.keys(this.charRanges)
.filter(function(r) { return opts[r]; })
.map(function(r) { return this.charRanges[r]; }, this);
if (!ranges.length) {
return '';
}
var randomBytes = kdbxweb.Random.getBytes(opts.length * 2);
var pos = 0;
while (pass.length < opts.length) {
var rangeNum = randomBytes[pos++] % ranges.length;
var range = ranges[rangeNum];
pass += range[randomBytes[pos++] % range.length];
}
return pass;
}
};
module.exports = PasswordGenerator;

View File

@ -18,6 +18,8 @@ var FooterView = Backbone.View.extend({
},
initialize: function () {
this.views = {};
KeyHandler.onKey(Keys.DOM_VK_L, this.lockWorkspace, this, KeyHandler.SHORTCUT_ACTION);
KeyHandler.onKey(Keys.DOM_VK_G, this.genPass, this, KeyHandler.SHORTCUT_ACTION);
KeyHandler.onKey(Keys.DOM_VK_O, this.openFile, this, KeyHandler.SHORTCUT_ACTION);
@ -36,14 +38,24 @@ var FooterView = Backbone.View.extend({
Backbone.trigger('lock-workspace');
},
genPass: function() {
genPass: function(e) {
e.stopPropagation();
if (this.views.gen) {
this.views.gen.remove();
return;
}
var el = this.$el.find('.footer__btn-generate'),
rect = el[0].getBoundingClientRect(),
bodyRect = document.body.getBoundingClientRect(),
right = bodyRect.right - rect.right,
bottom = bodyRect.bottom - rect.top;
var generator = new GeneratorView({ model: { pos: { right: right, bottom: bottom } } });
var generator = new GeneratorView({ model: {
pos: { right: right, bottom: bottom },
genOpts: this.model.settings.get('genOpts')
}});
generator.render();
generator.once('remove', (function() { delete this.views.gen; }).bind(this));
this.views.gen = generator;
},
showFile: function(e) {

View File

@ -1,6 +1,7 @@
'use strict';
var Backbone = require('backbone');
var Backbone = require('backbone'),
PasswordGenerator = require('../util/password-generator');
var GeneratorView = Backbone.View.extend({
el: 'body',
@ -8,20 +9,46 @@ var GeneratorView = Backbone.View.extend({
template: require('templates/generator.html'),
events: {
'mousedown': 'mousedown'
'click': 'click',
'mousemove .gen__length-range': 'lengthChange',
'change .gen__length-range': 'lengthChange',
'change .gen__check input[type=checkbox]': 'checkChange'
},
initialize: function () {
$('body').one('mousedown', this.remove.bind(this));
$('body').one('click', this.remove.bind(this));
this.gen = _.clone(this.model.genOpts);
},
render: function() {
this.renderTemplate();
this.renderTemplate(this.gen);
this.$el.css(this.model.pos);
this.generate();
},
mousedown: function(e) {
click: function(e) {
e.stopPropagation();
},
lengthChange: function(e) {
var val = +e.target.value;
if (val !== this.gen.length) {
this.gen.length = val;
this.$el.find('.gen__length-range-val').html(val);
this.generate();
}
},
checkChange: function(e) {
var id = $(e.target).data('id');
if (id) {
this.gen[id] = e.target.checked;
}
this.generate();
},
generate: function() {
this.$el.find('.gen__result').text(PasswordGenerator.generate(this.gen));
}
});

View File

@ -1,7 +1,21 @@
.gen {
position: absolute;
@include dropdown;
padding: $base-padding;
&__input-small {
padding: $base-spacing;
width: 10em;
&__length-range {
}
&__check {
width: 40%;
display: inline-block;
&:nth-child(even) {
margin-left: 15%;
}
}
&__result {
@include user-select(text);
font-family: $monospace-font-family;
margin-top: $base-padding-v;
white-space: nowrap;
}
}

View File

@ -138,3 +138,139 @@ option {
color: text-border();
}
}
input[type=checkbox] {
display: none;
& + label:hover:before {
@include th {
color: action-color();
}
}
& + label:before {
@include fa-icon;
content: $fa-var-square-o;
display: inline-block;
width: 1.3em;
@include th {
color: text-color();
}
}
&:checked + label:before {
content: $fa-var-check-square-o;
}
}
$thumb-size: 8px;
$track-width: 100%;
$track-height: 1px;
@mixin track {
@include size(100% 1px);
@include th { background: background-color(); }
cursor: pointer;
border: none;
}
@mixin thumb {
height: 1px;
width: 100%;
border: none;
border-radius: 1px;
cursor: pointer;
@include th { background: border-color(); }
}
&input[type=range] {
-webkit-appearance: none;
width: 100%;
margin: 12px 0;
&:focus {
outline: none;
}
&::-webkit-slider-runnable-track {
width: 100%;
height: 1px;
cursor: pointer;
@include th {
background: text-color();
}
border-radius: 1px;
border: none;
}
&::-webkit-slider-thumb {
border: none;
height: 14px;
width: 14px;
border-radius: 14px;
@include th {
background: text-color();
}
cursor: pointer;
-webkit-appearance: none;
margin-top: -6.5px;
}
// &:focus::-webkit-slider-runnable-track {
// @include th { background: active-color(); }
// }
&::-moz-range-track {
width: 100%;
height: 1px;
cursor: pointer;
@include th {
background: text-color();
}
border-radius: 1px;
border: none;
}
&::-moz-range-thumb {
border: none;
height: 14px;
width: 14px;
border-radius: 14px;
@include th {
background: text-color();
}
cursor: pointer;
}
&::-ms-track {
width: 100%;
height: 1px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
&::-ms-fill-lower {
@include th {
background: text-color();
}
border: none;
}
&::-ms-fill-upper {
@include th {
background: text-color();
}
border: none;
}
&::-ms-thumb {
border: none;
height: 14px;
width: 14px;
border-radius: 14px;
@include th {
background: text-color();
}
cursor: pointer;
}
&:focus::-ms-fill-lower {
@include th {
background: text-color();
}
}
&:focus::-ms-fill-upper {
@include th {
background: text-color();
}
}
}

View File

@ -2,6 +2,7 @@
$base-font-family: system, -apple-system, ".SFNSDisplay-Regular", "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
$font-family-text-thin: system, -apple-system, ".SFNSText-Light", "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
$heading-font-family: $base-font-family;
$monospace-font-family: monaco,Consolas,"Lucida Console",monospace;
// Font Sizes
$base-font-size: 12px;

View File

@ -1,20 +1,21 @@
<div class="gen">
<input type="text" class="gen__input-small" id="gen__text-len" value="16" maxlength="2" size="2" />
<label for="gen__text-len">symbols</label>
<div>Length: <span class="gen__length-range-val"><%= length %></span></div>
<input type="range" class="gen__length-range" value="16" min="2" max="32" />
<div>
<input type="checkbox" id="gen__check-upper" checked><label for="gen__check-upper">ABC</label>
<input type="checkbox" id="gen__check-lower" checked><label for="gen__check-lower">abc</label>
</div>
<div>
<input type="checkbox" id="gen__check-digits" checked><label for="gen__check-digits">123</label>
<input type="checkbox" id="gen__check-special"><label for="gen__check-special">!@#</label>
</div>
<div>
<input type="checkbox" id="gen__check-brackets"><label for="gen__check-brackets">({<</label>
<input type="checkbox" id="gen__check-high"><label for="gen__check-high">äæ±</label>
</div>
<div>
<input type="checkbox" id="gen__check-ambiguous"><label for="gen__check-ambiguous">0Oo</label>
<div class="gen__check"><input type="checkbox" id="gen__check-upper"
data-id="upper" <%= upper ? 'checked' : '' %>><label for="gen__check-upper">ABC</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-lower"
data-id="lower" <%= lower ? 'checked' : '' %>><label for="gen__check-lower">abc</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-digits"
data-id="digits" <%= digits ? 'checked' : '' %>><label for="gen__check-digits">123</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-special"
data-id="special" <%= special ? 'checked' : '' %>><label for="gen__check-special">!@#</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-brackets"
data-id="brackets" <%= brackets ? 'checked' : '' %>><label for="gen__check-brackets">({&lt;</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-high"
data-id="high" <%= high ? 'checked' : '' %>><label for="gen__check-high">äæ±</label></div>
<div class="gen__check"><input type="checkbox" id="gen__check-ambiguous"
data-id="ambiguous" <%= ambiguous ? 'checked' : '' %>><label for="gen__check-ambiguous">0Oo</label></div>
</div>
<div class="gen__result">password</div>
</div>
</div>