Przeglądaj źródła

👍

pull/342/head
Guillaume Vincent 7 lat temu
rodzic
commit
551f95383a
14 zmienionych plików z 527 dodań i 10567 usunięć
  1. +1
    -1
      .gitignore
  2. +2
    -2
      config/index.js
  3. +1
    -2
      index.html
  4. +0
    -10504
      package-lock.json
  5. +45
    -41
      package.json
  6. +1
    -1
      src/App.vue
  7. +197
    -3
      src/components/Index.vue
  8. +16
    -0
      src/components/OptionThumb.vue
  9. +2
    -2
      src/main.js
  10. +38
    -0
      src/services/copy-text-to-clipboard.js
  11. +60
    -0
      src/services/migration.js
  12. +154
    -0
      test.js
  13. +0
    -11
      test/unit/specs/Hello.spec.js
  14. +10
    -0
      test/unit/specs/Index.spec.js

+ 1
- 1
.gitignore Wyświetl plik

@@ -1,6 +1,6 @@
.DS_Store
node_modules/
dist/
docs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*


+ 2
- 2
config/index.js Wyświetl plik

@@ -4,8 +4,8 @@ var path = require('path')
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
index: path.resolve(__dirname, '../docs/index.html'),
assetsRoot: path.resolve(__dirname, '../docs'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,


+ 1
- 2
index.html Wyświetl plik

@@ -2,10 +2,9 @@
<html>
<head>
<meta charset="utf-8">
<title>lesspass-move</title>
<title>LessPass Move</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

+ 0
- 10504
package-lock.json
Plik diff jest za duży
Wyświetl plik


+ 45
- 41
package.json Wyświetl plik

@@ -9,66 +9,67 @@
"start": "node build/dev-server.js",
"build": "node build/build.js",
"unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
"test": "npm run unit"
"test": "cross-env BABEL_ENV=test ava test.js"
},
"dependencies": {
"ava": "^0.20.0",
"bootstrap": "^4.0.0-alpha.6",
"lesspass": "^6.0.0",
"lesspass-pure": "file:../pure",
"vue": "^2.3.3",
"vue": "^2.3.4",
"vue-polyglot": "^0.2.1",
"vue-router": "^2.3.1"
"vue-router": "^2.6.0"
},
"devDependencies": {
"autoprefixer": "^6.7.2",
"babel-core": "^6.22.1",
"babel-loader": "^6.2.10",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"autoprefixer": "^7.1.1",
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-plugin-istanbul": "^4.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.5.2",
"babel-preset-stage-2": "^6.24.1",
"babel-register": "^6.24.1",
"chai": "^4.0.2",
"chalk": "^1.1.3",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"cross-env": "^5.0.1",
"css-loader": "^0.28.4",
"eventsource-polyfill": "^0.9.6",
"express": "^4.14.1",
"extract-text-webpack-plugin": "^2.0.0",
"file-loader": "^0.11.1",
"friendly-errors-webpack-plugin": "^1.1.3",
"html-webpack-plugin": "^2.28.0",
"http-proxy-middleware": "^0.17.3",
"webpack-bundle-analyzer": "^2.2.1",
"cross-env": "^4.0.0",
"karma": "^1.4.1",
"express": "^4.15.3",
"extract-text-webpack-plugin": "^2.1.2",
"file-loader": "^0.11.2",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.29.0",
"http-proxy-middleware": "^0.17.4",
"inject-loader": "^3.0.0",
"karma": "^1.7.0",
"karma-coverage": "^1.1.1",
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.2",
"karma-phantomjs-launcher": "^1.0.4",
"karma-phantomjs-shim": "^1.4.0",
"karma-sinon-chai": "^1.3.1",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.30",
"karma-webpack": "^2.0.2",
"lolex": "^1.5.2",
"mocha": "^3.2.0",
"chai": "^3.5.0",
"sinon": "^2.1.0",
"sinon-chai": "^2.8.0",
"inject-loader": "^3.0.0",
"babel-plugin-istanbul": "^4.1.1",
"karma-spec-reporter": "0.0.31",
"karma-webpack": "^2.0.3",
"lolex": "^1.6.0",
"mocha": "^3.4.2",
"opn": "^5.1.0",
"optimize-css-assets-webpack-plugin": "^2.0.0",
"ora": "^1.3.0",
"phantomjs-prebuilt": "^2.1.14",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"opn": "^4.0.2",
"optimize-css-assets-webpack-plugin": "^1.3.0",
"ora": "^1.2.0",
"rimraf": "^2.6.0",
"url-loader": "^0.5.8",
"vue-loader": "^12.1.0",
"shelljs": "^0.7.8",
"sinon": "^2.3.5",
"sinon-chai": "^2.11.0",
"url-loader": "^0.5.9",
"vue-loader": "^12.2.1",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.3.3",
"webpack": "^2.6.1",
"webpack-dev-middleware": "^1.10.0",
"vue-template-compiler": "^2.3.4",
"webpack": "^3.0.0",
"webpack-bundle-analyzer": "^2.8.2",
"webpack-dev-middleware": "^1.11.0",
"webpack-hot-middleware": "^2.18.0",
"webpack-merge": "^4.1.0"
},
@@ -81,5 +82,8 @@
"last 2 versions",
"not ie <= 8"
],
"false": {}
"ava": {
"require": "babel-register",
"babel": "inherit"
}
}

+ 1
- 1
src/App.vue Wyświetl plik

@@ -1,6 +1,6 @@
<template>
<div id="app">
<app-menu></app-menu>
<!--<app-menu></app-menu>-->
<router-view></router-view>
</div>
</template>


+ 197
- 3
src/components/Index.vue Wyświetl plik

@@ -1,10 +1,204 @@
<template>
<div class="index">
index
<div class="container-fluid pt-3">
<div class="row">
<div class="col">
<h1>LessPass Move</h1>
</div>
</div>
<div class="row">
<div class="col">
<h3 class="mb-2">1 - Copy paste list of old profiles</h3>
</div>
</div>
<div class="row">
<div class="col">
<textarea id="oldProfiles" name="oldProfiles" class="form-control" rows="10" v-model="oldProfiles"
placeholder="Copy list of password profiles"></textarea>
</div>
</div>
<div class="row">
<div class="col">
<h3 class="mt-5 mb-2">2 - Set your(s) master password(s)</h3>
</div>
</div>
<div class="row">
<div class="col">
<form class="form-inline">
<input
id="oldMasterPassword"
type="password"
placeholder="Old Master Password"
v-model="oldMasterPassword">
<input
id="newMasterPassword"
type="password"
v-model="newMasterPassword"
placeholder="New Master Password"
v-if="changeMyMasterPassword">
</form>
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" v-model="changeMyMasterPassword">
Click me to change your master password at the same time
</label>
</div>
</div>
</div>
<div class="row">
<div class="col">
<h3 class="mt-5 mb-2">3 - Build your passwords:</h3>
</div>
</div>
<div class="row">
<div class="col">
<button class="btn btn-primary" v-on:click="buildAllPasswords()">Build all passwords</button>
</div>
</div>
<div class="row">
<div class="col">
<h3 class="mt-5 mb-2">4 - Copy paste old and new generated passwords:</h3>
</div>
</div>
<div class="row">
<div class="col">
<table class="table table-bordered table-sm">
<thead class="thead-inverse">
<tr>
<th class="text-center" colspan="8">Old profile</th>
<th></th>
<th class="text-center" colspan="8">New profile</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center"><b>site</b></td>
<td class="text-center"><b>login</b></td>
<td class="text-center"><b>a-z</b></td>
<td class="text-center"><b>A-Z</b></td>
<td class="text-center"><b>0-9</b></td>
<td class="text-center"><b>%!@</b></td>
<td class="text-center"><b>length</b></td>
<td class="text-center"><b>counter</b></td>
<td></td>
<td class="text-center"><b>site</b></td>
<td class="text-center"><b>login</b></td>
<td class="text-center"><b>a-z</b></td>
<td class="text-center"><b>A-Z</b></td>
<td class="text-center"><b>0-9</b></td>
<td class="text-center"><b>%!@</b></td>
<td class="text-center"><b>length</b></td>
<td class="text-center"><b>counter</b></td>
</tr>
<tr v-for="profile in newPasswordProfiles" v-if="profile.oldPassword!==profile.newPassword">
<td>
{{profile.oldProfile.site}}
</td>
<td>
{{profile.oldProfile.login}}
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.oldProfile.lowercase"></option-thumb>
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.oldProfile.uppercase"></option-thumb>
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.oldProfile.numbers"></option-thumb>
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.oldProfile.symbols"></option-thumb>
</td>
<td class="text-center"
v-bind:class="{'bg-warning': profile.oldProfile.length !== profile.newProfile.length }">
{{profile.oldProfile.length}}
</td>
<td class="text-center"
v-bind:class="{'bg-warning': profile.oldProfile.counter !== profile.newProfile.counter }">
{{profile.oldProfile.counter}}
</td>
<td class="text-center">
<button class="btn btn-default btn-sm" v-on:click="copyPassword(profile.oldPassword)">
<i class="fa fa-clipboard"></i>
</button>
<button class="btn btn-default btn-sm" v-on:click="copyPassword(profile.newPassword)">
<i class="fa fa-clipboard"></i>
</button>
</td>
<td>
{{profile.newProfile.site}}
</td>
<td>
{{profile.newProfile.login}}
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.newProfile.lowercase"></option-thumb>
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.newProfile.uppercase"></option-thumb>
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.newProfile.numbers"></option-thumb>
</td>
<td class="text-center">
<option-thumb :thumbUp="profile.newProfile.symbols"></option-thumb>
</td>
<td class="text-center"
v-bind:class="{'bg-warning': profile.oldProfile.length !== profile.newProfile.length }"
contenteditable="true">
{{profile.newProfile.length}}
</td>
<td class="text-center"
v-bind:class="{'bg-warning': profile.oldProfile.counter !== profile.newProfile.counter }">
{{profile.newProfile.counter}}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
import MasterPassword from 'lesspass-pure/src/components/MasterPassword.vue'
import migration from '@/services/migration';
import copy from '@/services/copy-text-to-clipboard';
import OptionThumb from '@/components/OptionThumb'
export default {
name: 'index'
name: 'index',
components: {
MasterPassword,
OptionThumb
},
data(){
return {
oldProfiles: "[]",
changeMyMasterPassword: false,
oldMasterPassword: '',
newMasterPassword: '',
newPasswordProfiles: []
}
},
methods: {
buildAllPasswords(){
var oldProfiles = JSON.parse(this.oldProfiles);
if (!this.changeMyMasterPassword) {
this.newMasterPassword = this.oldMasterPassword
}
migration.buildAllPasswords(migration.transformProfilesFromV1ToV2(oldProfiles), this.oldMasterPassword, this.newMasterPassword)
.then(newPasswordProfiles => {
this.newPasswordProfiles = newPasswordProfiles;
});
},
copyPassword(password){
const copied = copy(password);
},
clearProfileUpdate(profile){
var version = profile.newProfile.version;
profile.newProfile = profile.oldProfile;
profile.newProfile.version = version;
profile.updated = false;
}
}
}
</script>

+ 16
- 0
src/components/OptionThumb.vue Wyświetl plik

@@ -0,0 +1,16 @@
<template>
<div>
<i class="fa fa-thumbs-up text-success" v-if="thumbUp"></i>
<i class="fa fa-thumbs-down text-danger" v-else></i>
</div>
</template>
<script>
export default {
name: 'OptionThumb',
props: {
thumbUp: {
type: Boolean
}
},
}
</script>

+ 2
- 2
src/main.js Wyświetl plik

@@ -1,10 +1,10 @@
import Vue from 'vue'
import App from './App'
import App from './App.vue'
import 'lesspass-pure/dist/lesspass.min.css'
import router from './router'
import Polyglot from 'vue-polyglot';

Vue.use(Polyglot)
Vue.use(Polyglot);

new Vue({
el: '#app',


+ 38
- 0
src/services/copy-text-to-clipboard.js Wyświetl plik

@@ -0,0 +1,38 @@
'use strict';

module.exports = function (input) {
var el = document.createElement('textarea');

el.value = input;

// Prevent keyboard from showing on mobile
el.setAttribute('readonly', '');

el.style.contain = 'strict';
el.style.position = 'absolute';
el.style.left = '-9999px';
el.style.fontSize = '12pt'; // Prevent zooming on iOS

var selection = getSelection();
var originalRange = false;
if (selection.rangeCount > 0) {
originalRange = selection.getRangeAt(0);
}

document.body.appendChild(el);
el.select();

var success = false;
try {
success = document.execCommand('copy');
} catch (err) {}

document.body.removeChild(el);

if (originalRange) {
selection.removeAllRanges();
selection.addRange(originalRange);
}

return success;
};

+ 60
- 0
src/services/migration.js Wyświetl plik

@@ -0,0 +1,60 @@
import LessPass from 'lesspass';

export default {
transformProfilesFromV1ToV2: function(profiles) {
const newProfiles = [];
profiles.forEach(profile => {
const newProfile = {
"site": profile.site,
"login": profile.login,
"lowercase": profile.lowercase,
"uppercase": profile.uppercase,
"numbers": profile.numbers,
"symbols": profile.symbols,
"counter": profile.counter,
"length": profile.length,
"version": profile.version,
};
let updated = false;
if (profile.version === 1) {
newProfile.version = 2;
if (profile.length === 12) {
updated = true;
newProfile.length = 16;
}
}
newProfiles.push({
updated: updated,
oldProfile: profile,
newProfile: newProfile
})
});
return newProfiles
},
buildPromise(profile, masterPassword){
return LessPass.generatePassword(profile.site, profile.login, masterPassword, {
lowercase: profile.lowercase,
uppercase: profile.uppercase,
numbers: profile.numbers,
symbols: profile.symbols,
length: profile.length,
counter: profile.counter,
version: profile.version,
});
},
buildAllPasswords: function(profiles, oldMasterPassword, newMasterPassword) {
const buildPasswordPromises = [];
profiles.forEach(profile => {
buildPasswordPromises.push(this.buildPromise(profile.oldProfile, oldMasterPassword));
buildPasswordPromises.push(this.buildPromise(profile.newProfile, newMasterPassword));
});

return Promise.all(buildPasswordPromises).then(values => {
profiles.forEach((profile, i) => {
profile.oldPassword = values[i * 2];
profile.newPassword = values[i * 2 + 1]
});
return profiles;
});
}
};

+ 154
- 0
test.js Wyświetl plik

@@ -0,0 +1,154 @@
import test from 'ava';
import migration from './src/services/migration'

test('transformProfilesFromV1ToV2', t => {
var profiles = [
{
"site": "example.org",
"login": "test@example.org",
"lowercase": true,
"uppercase": true,
"numbers": true,
"symbols": true,
"counter": 1,
"length": 12,
"version": 1
},
{
"site": "bank.example.org",
"login": "test@example.org",
"lowercase": false,
"uppercase": false,
"numbers": true,
"symbols": false,
"counter": 2,
"length": 6,
"version": 1
},
{
"site": "example.com",
"login": "test@example.org",
"lowercase": true,
"uppercase": true,
"numbers": true,
"symbols": true,
"counter": 1,
"length": 16,
"version": 2
}
];
var expectedProfiles = [
{
oldProfile: profiles[0],
newProfile: {
"site": "example.org",
"login": "test@example.org",
"lowercase": true,
"uppercase": true,
"numbers": true,
"symbols": true,
"counter": 1,
"length": 16,
"version": 2
},
updated: true
},
{
oldProfile: profiles[1],
newProfile: {
"site": "bank.example.org",
"login": "test@example.org",
"lowercase": false,
"uppercase": false,
"numbers": true,
"symbols": false,
"counter": 2,
"length": 6,
"version": 2
},
updated: false
},
{
oldProfile: profiles[2],
newProfile: {
"site": "example.com",
"login": "test@example.org",
"lowercase": true,
"uppercase": true,
"numbers": true,
"symbols": true,
"counter": 1,
"length": 16,
"version": 2
},
updated: false
}
];
t.deepEqual(migration.transformProfilesFromV1ToV2(profiles), expectedProfiles);
});

test('buildAllPasswords', t => {
var profiles = [{
"site": "example.org",
"login": "test@example.org",
"lowercase": true,
"uppercase": true,
"numbers": true,
"symbols": true,
"counter": 1,
"length": 12,
"version": 1
}, {
"site": "bank.example.org",
"login": "test@example.org",
"lowercase": false,
"uppercase": false,
"numbers": true,
"symbols": false,
"counter": 2,
"length": 6,
"version": 1
}];

return migration
.buildAllPasswords(migration.transformProfilesFromV1ToV2(profiles), 'password', 'password')
.then(newPasswordProfiles => {
t.deepEqual(newPasswordProfiles[0].oldPassword, 'esIZ9,amEW5,');
t.deepEqual(newPasswordProfiles[0].newPassword, '[nYxh6=osW)aH99b');
t.deepEqual(newPasswordProfiles[1].oldPassword, '342387');
t.deepEqual(newPasswordProfiles[1].newPassword, '446545');
});
});

test('buildAllPasswords different master passwords', t => {
var profiles = [{
"site": "example.org",
"login": "test@example.org",
"lowercase": true,
"uppercase": true,
"numbers": true,
"symbols": true,
"counter": 1,
"length": 12,
"version": 1
}, {
"site": "bank.example.org",
"login": "test@example.org",
"lowercase": false,
"uppercase": false,
"numbers": true,
"symbols": false,
"counter": 2,
"length": 6,
"version": 1
}];

return migration
.buildAllPasswords(migration.transformProfilesFromV1ToV2(profiles), 'password', 'new_password')
.then(newPasswordProfiles => {
t.is(newPasswordProfiles[0].oldPassword, 'esIZ9,amEW5,');
t.is(newPasswordProfiles[0].newPassword, '\\-q5pba3wj1AHABY');
t.is(newPasswordProfiles[1].oldPassword, '342387');
t.is(newPasswordProfiles[1].newPassword, '559909');
});
});

+ 0
- 11
test/unit/specs/Hello.spec.js Wyświetl plik

@@ -1,11 +0,0 @@
import Vue from 'vue'
import Hello from '@/components/Hello'

describe('Hello.vue', () => {
it('should render correct contents', () => {
const Constructor = Vue.extend(Hello)
const vm = new Constructor().$mount()
expect(vm.$el.querySelector('.hello h1').textContent)
.to.equal('Welcome to Your Vue.js App')
})
})

+ 10
- 0
test/unit/specs/Index.spec.js Wyświetl plik

@@ -0,0 +1,10 @@
import Vue from 'vue'
import Hello from '@/components/Index'

describe('Index.vue', () => {
it('should render correct contents', () => {
const Constructor = Vue.extend(Hello);
const vm = new Constructor().$mount();
expect(vm.$el.querySelector('.index h1').textContent).to.equal('Index');
})
});

Ładowanie…
Anuluj
Zapisz