Browse Source

bootstrap 5 migration

b5
Guillaume Vincent 3 years ago
parent
commit
3779aa78b3
22 changed files with 364 additions and 732 deletions
  1. +3
    -3
      packages/lesspass-pure/cypress/integration/connectedMode.spec.js
  2. +1
    -1
      packages/lesspass-pure/cypress/integration/index.spec.js
  3. +5
    -21
      packages/lesspass-pure/cypress/integration/passwordGeneration.spec.js
  4. +1
    -2
      packages/lesspass-pure/package.json
  5. +1
    -33
      packages/lesspass-pure/src/LessPass.vue
  6. +0
    -147
      packages/lesspass-pure/src/components/InputSite.test.js
  7. +0
    -94
      packages/lesspass-pure/src/components/InputSite.vue
  8. +26
    -25
      packages/lesspass-pure/src/components/MasterPassword.vue
  9. +5
    -33
      packages/lesspass-pure/src/components/Menu.vue
  10. +3
    -3
      packages/lesspass-pure/src/components/Message.vue
  11. +106
    -120
      packages/lesspass-pure/src/components/Options.vue
  12. +0
    -1
      packages/lesspass-pure/src/main.js
  13. +10
    -16
      packages/lesspass-pure/src/store/actions.js
  14. +14
    -14
      packages/lesspass-pure/src/views/Login.vue
  15. +38
    -42
      packages/lesspass-pure/src/views/MyAccount.vue
  16. +64
    -77
      packages/lesspass-pure/src/views/PasswordGenerator.vue
  17. +25
    -29
      packages/lesspass-pure/src/views/PasswordReset.vue
  18. +20
    -26
      packages/lesspass-pure/src/views/PasswordResetConfirm.vue
  19. +2
    -2
      packages/lesspass-pure/src/views/Passwords.vue
  20. +21
    -23
      packages/lesspass-pure/src/views/Register.vue
  21. +15
    -11
      packages/lesspass-pure/src/views/Settings.vue
  22. +4
    -9
      packages/lesspass-pure/yarn.lock

+ 3
- 3
packages/lesspass-pure/cypress/integration/connectedMode.spec.js View File

@@ -10,7 +10,7 @@ describe("Connected Mode", function() {
cy.get("#fingerprint .fa-plane").should("be.visible");
cy.get("#signInButton").click();
cy.wait(500);
cy.get("#siteField").type("lesspass.com");
cy.get("#site").type("lesspass.com");
cy.get("#login").type("test@lesspass.com");
cy.get("#passwordField").type("test@lesspass.com");
cy.get("#generatePassword__btn").click();
@@ -32,7 +32,7 @@ describe("Connected Mode", function() {
cy.get("#passwordField").type("test@lesspass.com");
cy.wait(1000);
cy.get("#signInButton").click();
cy.get("#siteField").should("be.visible");
cy.get("#site").should("be.visible");
cy.get(".fa-key").should("be.visible");
cy.get(".fa-user")
.first()
@@ -60,7 +60,7 @@ describe("Connected Mode", function() {
cy.get(".passwordProfile__meta")
.first()
.click();
cy.get("#siteField").should("have.value", "example.org");
cy.get("#site").should("have.value", "example.org");
cy.get("#login").should("have.value", "contact@example.org");
cy.get(".fa-user")
.first()


+ 1
- 1
packages/lesspass-pure/cypress/integration/index.spec.js View File

@@ -6,6 +6,6 @@ describe("LessPass", function() {
it("should focus site field", function() {
cy.visit("/");
cy.wait(500);
cy.focused().should("have.id", "siteField");
cy.focused().should("have.id", "site");
});
});

+ 5
- 21
packages/lesspass-pure/cypress/integration/passwordGeneration.spec.js View File

@@ -18,7 +18,7 @@ describe("Password Generation", function() {

cy.visit("/");
cy.wait(500);
cy.get("#siteField")
cy.get("#site")
.type("lesspass.com")
.tab();
cy.get("#login").type("test@lesspass.com");
@@ -88,7 +88,7 @@ describe("Password Generation", function() {
it("should consider counter as string not hex value nrt_328", function() {
cy.visit("/");
cy.wait(500);
cy.get("#siteField").type("site");
cy.get("#site").type("site");
cy.get("#login").type("login");
cy.get("#passwordField").type("test");
cy.get("#passwordCounter")
@@ -100,7 +100,7 @@ describe("Password Generation", function() {
it("should generate password when hit enter nrt_266", function() {
cy.visit("/");
cy.wait(500);
cy.get("#siteField")
cy.get("#site")
.type("lesspass.com")
.tab();
cy.get("#login").type("test@lesspass.com");
@@ -109,26 +109,10 @@ describe("Password Generation", function() {
.type("{enter}");
cy.get("#generated-password").should("have.value", "hjV@\\5ULp3bIs,6B");
});
it("should keep site field in sync nrt_441", function() {
cy.visit("/");
cy.wait(500);
cy.get("#login").type("user");
cy.get("#passwordField").type("password");
cy.get("#siteField")
.type("subdomain.domain.com")
.type("{home}")
.type("{rightarrow}")
.type("{backspace}")
.type("{downarrow}")
.type("{downarrow}")
.type("{enter}");
cy.get("#generatePassword__btn").click();
cy.get("#generated-password").should("have.value", "ZT^IK2e!t@k$9`*)");
});
it("should clear password generated when master password change", function() {
cy.visit("/");
cy.wait(500);
cy.get("#siteField")
cy.get("#site")
.type("example.org")
.tab();
cy.get("#login").type("user");
@@ -144,7 +128,7 @@ describe("Password Generation", function() {
it("should generate password with 2 tabs and enter", function() {
cy.visit("/");
cy.wait(500);
cy.get("#siteField")
cy.get("#site")
.type("lesspass.com")
.tab()
.type("test@lesspass.com")


+ 1
- 2
packages/lesspass-pure/package.json View File

@@ -33,10 +33,9 @@
"dependencies": {
"@oslab/atob": "^0.1.0",
"@oslab/btoa": "^0.1.0",
"awesomplete": "^1.1.5",
"axios": "^0.21.1",
"balloon-css": "^1.0.3",
"bootstrap": "^4.6.0",
"bootstrap": "^5.0.0-beta3",
"copy-text-to-clipboard": "^3.0.1",
"core-js": "^3.9.1",
"font-awesome": "^4.7.0",


+ 1
- 33
packages/lesspass-pure/src/LessPass.vue View File

@@ -12,6 +12,7 @@
#lesspass {
color: #464646;
max-width: 420px;
position: relative;
}

.lesspass__inner-box {
@@ -24,43 +25,11 @@
}
}

#lesspass,
#lesspass * {
border-radius: 0 !important;
}

button,
.pointer {
cursor: pointer;
}

.inner-addon i {
position: absolute;
padding: 10px;
pointer-events: none;
z-index: 10;
}

.inner-addon {
position: relative;
}

.left-addon i {
left: 0;
}

.right-addon i {
right: 0;
}

.left-addon input {
padding-left: 30px;
}

.right-addon input {
padding-right: 30px;
}

#loading__view {
position: relative;
height: 358px;
@@ -177,7 +146,6 @@ export default {
}),
created() {
this.$store.dispatch("cleanMessage");
this.$store.dispatch("resetPassword");
const refresh = localStorage.getItem("refresh_token");
if (refresh) {
this.isLoading = true;


+ 0
- 147
packages/lesspass-pure/src/components/InputSite.test.js View File

@@ -1,147 +0,0 @@
import { mount } from "@vue/test-utils";
import InputSite from "./InputSite.vue";

jest.mock("../services/url-parser");
import { getSuggestions } from "../services/url-parser";

const createWrapper = data =>
mount({
data: () => {
return {
site: "",
passwords: [],
...data
};
},
template:
'<input-site v-model="site" v-bind:passwords="passwords" v-bind:label="\'Site\'"></input-site>',
components: { "input-site": InputSite }
});

const optionsFor = wrapper => wrapper.findAll("div.awesomplete li");
const inputField = wrapper => wrapper.find("#siteField");

describe("InputSite", () => {
beforeEach(() => {
getSuggestions.mockImplementation(() => []);
});

it("fills the input with the value property", () => {
const wrapper = createWrapper({ site: "lesspass.com" });
const input = inputField(wrapper);
expect(input.element.value).toBe("lesspass.com");
});

// todo fix autocomplete tests
describe.skip("autocomplete", function() {
describe("search", () => {
it("filters according to site name", () => {
const wrapper = createWrapper({
passwords: [
{ site: "lesspass", login: "xavier" },
{ site: "wrongsite", login: "xavier" }
]
});
inputField(wrapper).setValue("le");
let options = optionsFor(wrapper);
expect(options.length).toBe(1);
expect(options.at(0).text()).toBe("lesspass xavier");
});
it(`shows options that are contained in the user's value`, () => {
const wrapper = createWrapper({
passwords: [{ site: "lesspass", login: "xavier" }]
});
inputField(wrapper).setValue("www.lesspass.com");
let options = optionsFor(wrapper);
expect(options.length).toBe(1);
expect(options.at(0).text()).toBe("lesspass xavier");
});
it("filters using suggestion", () => {
getSuggestions.mockImplementation(() => []);
const wrapper = createWrapper();
getSuggestions.mockImplementation(() => ["lesspass"]);
inputField(wrapper).setValue("lesspass.com");
let options = optionsFor(wrapper);
expect(options.length).toBe(1);
expect(options.at(0).text()).toBe("lesspass");
});
it("shows site and login in the list", () => {
const wrapper = createWrapper({
passwords: [{ site: "lesspass", login: "xavier" }]
});
inputField(wrapper).setValue("le");
let options = optionsFor(wrapper);
expect(options.length).toBe(1);
expect(options.at(0).text()).toBe("lesspass xavier");
});
it(`doesn't use login`, () => {
const wrapper = createWrapper({
passwords: [{ site: "lesspass", login: "xavier" }]
});
inputField(wrapper).setValue("xa");
let options = optionsFor(wrapper);
expect(options.length).toBe(0);
});
it(`prints options sorted by site then login`, () => {
const wrapper = createWrapper({
passwords: [
{ site: "lesspass", login: "guillaume" },
{ site: "passless", login: "xavier" },
{ site: "passless", login: "guillaume" },
{ site: "lesspass", login: "xavier" }
]
});
inputField(wrapper).setValue("le");
let options = optionsFor(wrapper);
expect(options.length).toBe(4);
expect(options.at(0).text()).toBe("lesspass guillaume");
expect(options.at(1).text()).toBe("lesspass xavier");
expect(options.at(2).text()).toBe("passless guillaume");
expect(options.at(3).text()).toBe("passless xavier");
});
});
describe("completion", () => {
describe("when selecting password", () => {
let wrapper;
beforeEach(() => {
wrapper = createWrapper({
passwords: [{ site: "lesspass", login: "xavier" }]
});
inputField(wrapper).setValue("le");
const options = optionsFor(wrapper);
options.at(0).trigger("click");
});
it("completes field", () => {
expect(inputField(wrapper).element.value).toBe("lesspass");
});
it('emits a "passwordProfileSelected" with the value', () => {
const emitted = wrapper.findComponent(InputSite).emitted();
const profileSelected = emitted["passwordProfileSelected"];
expect(profileSelected.length).toBe(1);
expect(profileSelected[0]).toEqual([
{ site: "lesspass", login: "xavier" }
]);
});
});
});
describe("when selecting suggestion", () => {
let wrapper;
beforeEach(() => {
getSuggestions.mockImplementation(() => ["lesspass"]);
wrapper = createWrapper();
inputField(wrapper).setValue("le");
const options = optionsFor(wrapper);
options.at(0).trigger("click");
});
it("completes field", () => {
expect(inputField(wrapper).element.value).toBe("lesspass");
});
it('emits a "suggestionSelected" with site value', () => {
const emitted = wrapper.findComponent(InputSite).emitted();
const profileSelected = emitted["suggestionSelected"];
expect(profileSelected.length).toBe(1);
expect(profileSelected[0]).toEqual(["lesspass"]);
});
});
});
});

+ 0
- 94
packages/lesspass-pure/src/components/InputSite.vue View File

@@ -1,94 +0,0 @@
<style>
.awesomplete mark {
background-color: transparent !important;
padding: 0;
margin: 0;
color: inherit;
}
</style>
<template>
<div class="inputSite">
<label for="siteField" class="sr-only">{{ label }}</label>
<div class="inner-addon left-addon">
<i class="fa fa-globe"></i>
<input
id="siteField"
type="text"
name="siteField"
ref="siteField"
class="form-control awesomplete"
tabindex="0"
autocorrect="off"
autocapitalize="none"
v-bind:placeholder="label"
v-model="site"
/>
</div>
</div>
</template>
<script>
import Awesomplete from "awesomplete";
import { getSuggestions } from "../services/url-parser";

export default {
name: "inputSite",
props: {
value: String,
label: String,
passwords: {
type: Array,
default: () => []
}
},
mounted() {
this.awesomplete = new Awesomplete(this.$refs.siteField);
this.awesomplete.item = (element, input) => {
let item = Awesomplete.ITEM(element.value.site, input);
item.innerHTML += ` ${element.value.login}`;
return item;
};
this.awesomplete.filter = (site, input) => {
return (
Awesomplete.FILTER_CONTAINS(site, input) ||
Awesomplete.FILTER_CONTAINS(input, site)
);
};
this.awesomplete.data = data => {
return { label: data.site, value: data };
};
this.awesomplete.replace = password => {
this.$refs.siteField.value = password.label;
if (password.value.suggestion) {
this.$emit("suggestionSelected", password.value.site);
} else {
this.$emit("passwordProfileSelected", password.value);
}
};
this.awesomplete.sort = (a, b) => {
return (
a.value.site.localeCompare(b.value.site) ||
a.value.login.localeCompare(b.value.login)
);
};
},
computed: {
site: {
get: function() {
return this.value;
},
set: function(newValue) {
this.$emit("input", newValue);
}
}
},
watch: {
site: function(newValue) {
const suggestions = getSuggestions(newValue).map(suggestion => {
return { site: suggestion, suggestion: true, login: "" };
});
this.awesomplete.list = this.passwords.concat(suggestions);
}
},
methods: {}
};
</script>

+ 26
- 25
packages/lesspass-pure/src/components/MasterPassword.vue View File

@@ -16,9 +16,9 @@
</style>
<template>
<div class="masterPassword">
<div class="input-group inner-addon left-addon">
<label for="passwordField" class="sr-only">{{ label }}</label>
<i class="fa fa-lock"></i>
<label for="passwordField" class="sr-only">{{ label }}</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-lock"></i></span>
<input
id="passwordField"
name="passwordField"
@@ -33,31 +33,32 @@
v-on:input="updateValue($event.target.value)"
v-on:keyup.enter="$emit('keyupEnter')"
/>
<span
class="input-group-btn"
<button
id="fingerprint"
class="btn"
type="button"
tabindex="-1"
v-if="fingerprint && value"
v-on:click="togglePasswordType"
>
<button id="fingerprint" class="btn" type="button" tabindex="-1">
<small>
<i
class="fa fa-fw"
v-bind:class="[icon1]"
v-bind:style="{ color: color1 }"
></i>
<i
class="fa fa-fw"
v-bind:class="[icon2]"
v-bind:style="{ color: color2 }"
></i>
<i
class="fa fa-fw"
v-bind:class="[icon3]"
v-bind:style="{ color: color3 }"
></i>
</small>
</button>
</span>
<small>
<i
class="fa fa-fw"
v-bind:class="[icon1]"
v-bind:style="{ color: color1 }"
></i>
<i
class="fa fa-fw"
v-bind:class="[icon2]"
v-bind:style="{ color: color2 }"
></i>
<i
class="fa fa-fw"
v-bind:class="[icon3]"
v-bind:style="{ color: color3 }"
></i>
</small>
</button>
</div>
</div>
</template>


+ 5
- 33
packages/lesspass-pure/src/components/Menu.vue View File

@@ -25,25 +25,9 @@
>LessPass</span
>
</div>
<div class="col-8 text-right">
<span v-if="saved && isAuthenticated">
<small><i class="fa fa-lg fa-check pl-3"></i> saved</small>
</span>
<span
class="white-link"
v-on:click="saveOrUpdatePassword()"
v-if="
!saved &&
isAuthenticated &&
$store.state.password.site !== '' &&
$store.state.route.path === '/'
"
:title="$t('Save')"
>
<i class="fa fa-lg fa-save pointer"></i>
</span>
<div class="col-8 text-end">
<router-link
class="white-link pl-3"
class="white-link ps-3"
:to="{ name: 'passwords' }"
v-if="isAuthenticated"
:title="$t('Saved passwords')"
@@ -51,14 +35,14 @@
<i class="fa fa-lg fa-key"></i>
</router-link>
<router-link
class="white-link pl-3"
class="white-link ps-3"
:to="{ name: 'settings' }"
:title="$t('Settings')"
>
<i class="fa fa-lg fa-cog"></i>
</router-link>
<router-link
class="white-link pl-3"
class="white-link ps-3"
:to="{ name: 'myaccount' }"
v-if="isAuthenticated"
:title="$t('My Account')"
@@ -66,7 +50,7 @@
<i class="fa fa-lg fa-user pointer"></i>
</router-link>
<router-link
class="white-link pl-3"
class="white-link ps-3"
:to="{ name: 'login' }"
v-if="isGuest"
:title="$t('Sign In')"
@@ -82,22 +66,10 @@
import { mapGetters } from "vuex";

export default {
data() {
return {
saved: false
};
},
methods: {
fullReload() {
this.$store.dispatch("resetPassword");
this.$router.push({ name: "home" }).catch(e => {});
},
saveOrUpdatePassword() {
this.$store.dispatch("saveOrUpdatePassword");
this.saved = true;
setTimeout(() => {
this.saved = false;
}, 3000);
}
},
computed: {


+ 3
- 3
packages/lesspass-pure/src/components/Message.vue View File

@@ -14,7 +14,7 @@

#message {
position: absolute;
top: 49px;
top: 41px;
left: 0;
right: 0;
z-index: 20;
@@ -23,8 +23,8 @@
.close-notification {
float: right;
position: absolute;
top: 0;
right: 1em;
top: 10px;
right: 16px;
cursor: pointer;
}
</style>


+ 106
- 120
packages/lesspass-pure/src/components/Options.vue View File

@@ -11,92 +11,84 @@
</style>
<template>
<div id="options">
<div class="form-group row">
<div class="col-12">
<div class="row">
<div class="col">
<label for="types">{{ $t("Options") }}</label>
<div class="row mb-2">
<label for="types">{{ $t("Options") }}</label>
<div id="types" class="row">
<div class="col-3">
<div class="form-check">
<input
id="lowercase__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.lowercase"
/>
<label class="form-check-label" for="lowercase__btn">
a-z
</label>
</div>
</div>
<div id="types" class="row">
<div class="col-3">
<div class="form-check">
<input
id="lowercase__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.lowercase"
/>
<label class="form-check-label" for="lowercase__btn">
a-z
</label>
</div>
</div>
<div class="col-3">
<div class="form-check">
<input
id="uppercase__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.uppercase"
/>
<label class="form-check-label" for="uppercase__btn">
A-Z
</label>
</div>
<div class="col-3">
<div class="form-check">
<input
id="uppercase__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.uppercase"
/>
<label class="form-check-label" for="uppercase__btn">
A-Z
</label>
</div>
<div class="col-3">
<div class="form-check">
<input
id="numbers__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.numbers"
/>
<label class="form-check-label" for="numbers__btn">
0-9
</label>
</div>
</div>
<div class="col-3">
<div class="form-check">
<input
id="numbers__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.numbers"
/>
<label class="form-check-label" for="numbers__btn">
0-9
</label>
</div>
<div class="col-3">
<div class="form-check">
<input
id="symbols__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.symbols"
/>
<label class="form-check-label" for="symbols__btn">
%!@
</label>
</div>
</div>
<div class="col-3">
<div class="form-check">
<input
id="symbols__btn"
type="checkbox"
tabindex="1"
class="form-check-input"
v-model="options.symbols"
/>
<label class="form-check-label" for="symbols__btn">
%!@
</label>
</div>
</div>
</div>
</div>
<div class="form-group row mb-0">
<div class="row">
<div class="col-5 col-sm-4">
<label for="passwordLength">{{ $t("Length") }}</label>
<div class="input-group input-group-sm">
<span class="input-group-btn">
<button
id="decreaseLength__btn"
class="btn btn-primary btn-sm px-2"
tabindex="1"
type="button"
v-on:click="
options.length = decrement(options.length, { min: 5, max: 35 })
"
>
<small>
<i class="fa fa-minus"></i>
</small>
</button>
</span>
<button
id="decreaseLength__btn"
class="btn btn-primary px-2"
tabindex="1"
type="button"
v-on:click="
options.length = decrement(options.length, { min: 5, max: 35 })
"
>
<small>
<i class="fa fa-minus"></i>
</small>
</button>
<input
id="passwordLength"
class="form-control form-control-sm"
@@ -106,21 +98,19 @@
max="35"
v-model.number="options.length"
/>
<span class="input-group-btn">
<button
id="increaseLength__btn"
class="btn btn-primary btn-sm px-2"
tabindex="1"
type="button"
v-on:click="
options.length = increment(options.length, { min: 5, max: 35 })
"
>
<small>
<i class="fa fa-plus"></i>
</small>
</button>
</span>
<button
id="increaseLength__btn"
class="btn btn-primary px-2"
tabindex="1"
type="button"
v-on:click="
options.length = increment(options.length, { min: 5, max: 35 })
"
>
<small>
<i class="fa fa-plus"></i>
</small>
</button>
</div>
</div>
<div class="col-5 col-sm-4">
@@ -137,21 +127,19 @@
>{{ $t("Counter") }}</label
>
<div class="input-group input-group-sm">
<span class="input-group-btn">
<button
id="decreaseCounter__btn"
class="btn btn-primary btn-sm px-2"
tabindex="1"
type="button"
v-on:click="
options.counter = decrement(options.counter, { min: 1 })
"
>
<small>
<i class="fa fa-minus"></i>
</small>
</button>
</span>
<button
id="decreaseCounter__btn"
class="btn btn-primary px-2"
tabindex="1"
type="button"
v-on:click="
options.counter = decrement(options.counter, { min: 1 })
"
>
<small>
<i class="fa fa-minus"></i>
</small>
</button>
<input
id="passwordCounter"
class="form-control form-control-sm"
@@ -160,21 +148,19 @@
min="1"
v-model.number="options.counter"
/>
<span class="input-group-btn">
<button
id="increaseCounter__btn"
class="btn btn-primary btn-sm px-2"
tabindex="1"
type="button"
v-on:click="
options.counter = increment(options.counter, { min: 1 })
"
>
<small>
<i class="fa fa-plus"></i>
</small>
</button>
</span>
<button
id="increaseCounter__btn"
class="btn btn-primary px-2"
tabindex="1"
type="button"
v-on:click="
options.counter = increment(options.counter, { min: 1 })
"
>
<small>
<i class="fa fa-plus"></i>
</small>
</button>
</div>
</div>
</div>


+ 0
- 1
packages/lesspass-pure/src/main.js View File

@@ -8,7 +8,6 @@ import router from "./router";
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.css";
import "balloon-css/balloon.css";
import "awesomplete/awesomplete.css";

import { languagesAvailable, locales } from "./i18n";



+ 10
- 16
packages/lesspass-pure/src/store/actions.js View File

@@ -49,22 +49,16 @@ export const getPasswords = ({ commit }) => {
});
};

export const saveOrUpdatePassword = ({ commit, state }) => {
const site = state.password.site;
const login = state.password.login;
const existingPassword = state.passwords.find(password => {
return password.site === site && password.login === login;
});
if (existingPassword) {
const newPassword = Object.assign({}, existingPassword, state.password);
Password.update(newPassword, state).then(() => {
getPasswords({ commit, state });
});
} else {
Password.create(state.password, state).then(() => {
getPasswords({ commit, state });
});
}
export const createPassword = ({ commit, state }) => {
return Password.create(state.password, state).then(() =>
getPasswords({ commit, state })
);
};

export const updatePassword = ({ commit, state }) => {
return Password.update(state.password, state).then(() =>
getPasswords({ commit, state })
);
};

export const deletePassword = ({ commit, state }, payload) => {


+ 14
- 14
packages/lesspass-pure/src/views/Login.vue View File

@@ -1,8 +1,8 @@
<template>
<form v-on:submit.prevent="signIn">
<div class="form-group">
<div class="inner-addon left-addon">
<i class="fa fa-globe"></i>
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-globe"></i></span>
<input
id="baseURL"
type="text"
@@ -13,9 +13,9 @@
/>
</div>
</div>
<div class="form-group">
<div class="inner-addon left-addon">
<i class="fa fa-user"></i>
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-user"></i></span>
<input
id="email"
class="form-control"
@@ -28,13 +28,13 @@
/>
</div>
</div>
<div class="form-group mb-1">
<div class="mb-1">
<master-password
v-model="password"
v-bind:label="$t('Master Password')"
></master-password>
</div>
<div class="form-check form-switch mb-3">
<div class="form-check mb-3">
<input
id="encryptMasterPassword"
class="form-check-input"
@@ -47,26 +47,26 @@
</small>
</label>
</div>
<div class="form-group">
<button id="signInButton" class="btn btn-primary btn-block">
<div class="mb-3 d-grid">
<button id="signInButton" class="btn btn-primary">
{{ $t("Sign In") }}
</button>
</div>
<div class="form-group">
<div class="mb-3">
<button
id="login__forgot-password-btn"
type="button"
class="btn btn-link btn-sm p-0"
class="btn btn-link p-0"
v-on:click="$router.push({ name: 'passwordReset' })"
>
<small>{{ $t("ForgotPassword", "Forgot your password?") }}</small>
</button>
</div>
<div class="form-group mb-0">
<div class="mb-0 d-grid">
<button
id="login__no-account-btn"
type="button"
class="btn btn-light btn-block"
class="btn btn-outline-dark"
v-on:click="$router.push({ name: 'register' })"
>
<small>{{


+ 38
- 42
packages/lesspass-pure/src/views/MyAccount.vue View File

@@ -1,55 +1,51 @@
<template>
<div>
<h5>{{ $t("Change my password") }}</h5>
<div class="mb-3">
<h5>{{ $t("Change my password") }}</h5>
</div>
<form v-on:submit.prevent="changePassword">
<div class="form-group row">
<div class="col-12">
<div class="inner-addon left-addon">
<i class="fa fa-user"></i>
<input
id="email"
class="form-control"
name="email"
type="email"
placeholder="Email"
v-model="email"
/>
</div>
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-user"></i></span>
<input
id="email"
class="form-control"
name="email"
type="email"
placeholder="Email"
v-model="email"
/>
</div>
</div>
<div class="form-group row">
<div class="col-12">
<master-password
v-model="current_password"
v-bind:label="$t('Current Master Password')"
></master-password>
</div>
<div class="mb-3">
<master-password
v-model="current_password"
v-bind:label="$t('Current Master Password')"
></master-password>
</div>
<div class="form-group row">
<div class="col-12">
<master-password
v-model="new_password"
v-bind:label="$t('New Master Password')"
></master-password>
</div>
<div class="mb-3">
<master-password
v-model="new_password"
v-bind:label="$t('New Master Password')"
></master-password>
</div>
<div class="form-group row">
<div class="col-12">
<button id="changeMyPasswordButton" class="btn btn-primary btn-block">
{{ $t("Change my password") }}
</button>
</div>
<div class="mb-3">
<button id="changeMyPasswordButton" class="btn btn-primary">
{{ $t("Change my password") }}
</button>
</div>
</form>
<hr />
<button
id="signOutButton"
class="btn btn-success btn-block"
type="button"
v-on:click="logout"
>
{{ $t("Sign out") }}
</button>
<div>
<button
id="signOutButton"
class="btn btn-success"
type="button"
v-on:click="logout"
>
{{ $t("Sign out") }}
</button>
</div>
</div>
</template>
<script>


+ 64
- 77
packages/lesspass-pure/src/views/PasswordGenerator.vue View File

@@ -2,14 +2,6 @@
#generated-password {
font-family: Consolas, Menlo, Monaco, Courier New, monospace, sans-serif;
}

div.awesomplete {
display: block;
}

div.awesomplete > ul {
z-index: 11;
}
</style>
<template>
<form
@@ -17,21 +9,29 @@ div.awesomplete > ul {
v-on:submit.prevent="generatePassword"
novalidate
>
<div class="form-group">
<input-site
ref="site"
v-model="password.site"
v-bind:passwords="passwords"
v-bind:label="$t('Site')"
v-on:suggestionSelected="setSite"
v-on:passwordProfileSelected="setPasswordProfile"
></input-site>
<div class="mb-3">
<label for="site" class="sr-only">{{ $t("Site") }}</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-globe"></i></span>
<input
id="site"
type="text"
name="site"
ref="site"
class="form-control"
tabindex="0"
autocorrect="off"
autocapitalize="none"
v-bind:placeholder="$t('Site')"
v-model="password.site"
/>
</div>
</div>
<remove-auto-complete></remove-auto-complete>
<div class="form-group">
<div class="mb-3">
<label for="login" class="sr-only">{{ $t("Username") }}</label>
<div class="inner-addon left-addon">
<i class="fa fa-user"></i>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-user"></i></span>
<input
id="login"
type="text"
@@ -47,67 +47,63 @@ div.awesomplete > ul {
/>
</div>
</div>
<div class="form-group">
<div class="mb-3">
<master-password
ref="masterPassword"
v-model="masterPassword"
v-bind:label="$t('Master Password')"
></master-password>
</div>
<options v-bind:options="password"></options>
<div class="form-group mt-4 mb-0">
<div class="mb-4">
<options v-bind:options="password"></options>
</div>
<div class="mb-0 d-grid">
<button
id="generatePassword__btn"
type="submit"
tabindex="0"
class="btn btn-primary btn-block"
class="btn btn-primary"
v-if="!passwordGenerated"
>
{{ $t("Generate") }}
</button>
<div class="input-group" v-show="passwordGenerated">
<span class="input-group-btn">
<button
id="copyPasswordButton"
class="btn btn-primary"
tabindex="0"
type="button"
v-on:click="copyPassword()"
>
<i class="fa fa-clipboard"></i>
</button>
</span>
<input
id="generated-password"
type="password"
class="form-control"
tabindex="-1"
ref="passwordGenerated"
v-bind:value="passwordGenerated"
/>
<span class="input-group-btn">
<button
id="revealGeneratedPassword"
type="button"
class="btn btn-secondary"
tabindex="0"
v-on:click="togglePasswordType($refs.passwordGenerated)"
>
<i class="fa fa-eye"></i>
</button>
</span>
<span class="input-group-btn">
<button
id="sharePasswordProfileButton"
type="button"
class="btn btn-secondary"
tabindex="0"
v-on:click="sharePasswordProfile()"
>
<i class="fa fa-share-alt pointer"></i>
</button>
</span>
</div>
</div>
<div class="input-group" v-show="passwordGenerated">
<button
id="copyPasswordButton"
class="btn btn-primary"
tabindex="0"
type="button"
v-on:click="copyPassword()"
>
<i class="fa fa-clipboard"></i>
</button>
<input
id="generated-password"
type="password"
class="form-control"
tabindex="-1"
ref="passwordGenerated"
v-bind:value="passwordGenerated"
/>
<button
id="revealGeneratedPassword"
type="button"
class="btn btn-secondary"
tabindex="0"
v-on:click="togglePasswordType($refs.passwordGenerated)"
>
<i class="fa fa-eye"></i>
</button>
<button
id="sharePasswordProfileButton"
type="button"
class="btn btn-secondary"
tabindex="0"
v-on:click="sharePasswordProfile()"
>
<i class="fa fa-share-alt"></i>
</button>
</div>
</form>
</template>
@@ -117,7 +113,6 @@ import { mapGetters, mapState } from "vuex";
import copy from "copy-text-to-clipboard";
import RemoveAutoComplete from "../components/RemoveAutoComplete.vue";
import MasterPassword from "../components/MasterPassword.vue";
import InputSite from "../components/InputSite.vue";
import Options from "../components/Options.vue";
import { showTooltip, hideTooltip } from "../services/tooltip";
import message from "../services/message";
@@ -127,7 +122,6 @@ export default {
name: "password-generator-view",
components: {
RemoveAutoComplete,
InputSite,
MasterPassword,
Options
},
@@ -245,7 +239,7 @@ export default {
},
focusBestInputField() {
try {
const site = this.$refs.site.$refs.siteField;
const site = this.$refs.site;
const login = this.$refs.login;
const masterPassword = this.$refs.masterPassword;
if (site && !site.value) return void site.focus();
@@ -285,13 +279,6 @@ export default {
},
setSite(site) {
this.password.site = site;
},
setPasswordProfile(passwordProfile) {
this.$store
.dispatch("savePassword", { password: passwordProfile })
.then(() => {
this.focusBestInputField();
});
}
}
};


+ 25
- 29
packages/lesspass-pure/src/views/PasswordReset.vue View File

@@ -1,36 +1,32 @@
<template>
<form v-on:submit.prevent="resetPassword">
<div class="form-group row">
<div class="col-12">
<label for="email">{{ $t("Email") }}</label>
<div class="inner-addon left-addon">
<i class="fa fa-user"></i>
<input
id="email"
class="form-control"
name="email"
type="email"
v-bind:placeholder="$t('Email')"
v-model="email"
/>
</div>
<small id="emailHelp" class="form-text text-muted">{{
$t(
"ResetPasswordHelpText",
"Enter your user account's verified email address and we will send you a password reset link."
)
}}</small>
<div class="mb-3">
<label for="email">{{ $t("Email") }}</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-user"></i></span>
<input
id="email"
class="form-control"
name="email"
type="email"
v-bind:placeholder="$t('Email')"
v-model="email"
/>
</div>
<small id="emailHelp" class="form-text text-muted">{{
$t(
"ResetPasswordHelpText",
"Enter your user account's verified email address and we will send you a password reset link."
)
}}</small>
</div>
<div class="form-group row">
<div class="col-12">
<button
id="password-reset__reset-password-btn"
class="btn btn-primary btn-block"
>
{{ $t("Reset my password") }}
</button>
</div>
<div class="mb-3 d-grid">
<button
id="password-reset__reset-password-btn"
class="btn btn-primary"
>
{{ $t("Reset my password") }}
</button>
</div>
</form>
</template>


+ 20
- 26
packages/lesspass-pure/src/views/PasswordResetConfirm.vue View File

@@ -1,34 +1,28 @@
<template>
<form v-on:submit.prevent="resetPasswordConfirm">
<div class="form-group row">
<div class="col-12">
<div class="inner-addon left-addon">
<i class="fa fa-user"></i>
<input
id="email"
class="form-control"
name="email"
type="email"
placeholder="Email"
v-model="email"
/>
</div>
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-user"></i></span>
<input
id="email"
class="form-control"
name="email"
type="email"
placeholder="Email"
v-model="email"
/>
</div>
</div>
<div class="form-group row">
<div class="col-12">
<master-password
v-model="password"
v-bind:label="$t('Master Password')"
></master-password>
</div>
<div class="mb-3">
<master-password
v-model="password"
v-bind:label="$t('Master Password')"
></master-password>
</div>
<div class="form-group row">
<div class="col-12">
<button id="resetMyPasswordButton" class="btn btn-primary btn-block">
{{ $t("Reset my password") }}
</button>
</div>
<div class="mb-3 d-grid">
<button id="resetMyPasswordButton" class="btn btn-primary">
{{ $t("Reset my password") }}
</button>
</div>
</form>
</template>


+ 2
- 2
packages/lesspass-pure/src/views/Passwords.vue View File

@@ -16,8 +16,8 @@
<div id="passwords__search" class="pb-3">
<div class="row">
<div class="col">
<div class="inner-addon left-addon">
<i class="fa fa-search"></i>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-search"></i></span>
<input
class="form-control"
type="text"


+ 21
- 23
packages/lesspass-pure/src/views/Register.vue View File

@@ -1,8 +1,8 @@
<template>
<form v-on:submit.prevent="signIn">
<div class="form-group">
<div class="inner-addon left-addon">
<i class="fa fa-globe"></i>
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-globe"></i></span>
<input
id="baseURL"
type="text"
@@ -13,44 +13,42 @@
/>
</div>
</div>
<div class="form-group row">
<div class="col-12">
<div class="inner-addon left-addon">
<i class="fa fa-user"></i>
<input
id="email"
class="form-control"
name="username"
type="email"
autocapitalize="none"
v-bind:placeholder="$t('Email')"
required
v-model="email"
/>
</div>
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-user"></i></span>
<input
id="email"
class="form-control"
name="username"
type="email"
autocapitalize="none"
v-bind:placeholder="$t('Email')"
required
v-model="email"
/>
</div>
</div>
<div class="form-group">
<div class="mb-3">
<master-password
v-model="password"
v-bind:label="$t('Master Password')"
></master-password>
</div>
<div class="form-group">
<div class="mb-3 d-grid">
<button
id="registerButton"
class="btn btn-primary btn-block"
class="btn btn-primary"
type="button"
v-on:click="register"
>
{{ $t("Register") }}
</button>
</div>
<div class="form-group mb-0">
<div class="mb-0 d-grid">
<button
id="login__no-account-btn"
type="button"
class="btn btn-light btn-block"
class="btn btn-outline-dark"
v-on:click="$router.push({ name: 'login' })"
>
<small>{{


+ 15
- 11
packages/lesspass-pure/src/views/Settings.vue View File

@@ -1,15 +1,17 @@
<template>
<div>
<h5>{{ $t("Options by default") }}</h5>
<div class="mb-3">
<h5>{{ $t("Options by default") }}</h5>
</div>
<form
id="lesspass-options-form"
novalidate
v-on:submit.prevent="saveAndExit"
>
<div class="form-group">
<div class="mb-3">
<label for="login">{{ $t("Username") }}</label>
<div class="inner-addon left-addon">
<i class="fa fa-user"></i>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-user"></i></span>
<input
id="login"
type="text"
@@ -25,13 +27,15 @@
</div>
</div>
<options v-bind:options="defaultPassword"></options>
<button
type="submit"
id="btn-submit-settings"
class="btn btn-primary btn-block mt-4"
>
{{ $t("Save") }}
</button>
<div>
<button
type="submit"
id="btn-submit-settings"
class="btn btn-primary mt-4"
>
{{ $t("Save") }}
</button>
</div>
</form>
</div>
</template>


+ 4
- 9
packages/lesspass-pure/yarn.lock View File

@@ -2602,11 +2602,6 @@ autoprefixer@^9.8.6:
postcss "^7.0.32"
postcss-value-parser "^4.1.0"

awesomplete@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/awesomplete/-/awesomplete-1.1.5.tgz#1b2b5dd106d3955595619c03da472a1dc0faf0af"
integrity sha512-UFw1mPW8NaSECDSTC36HbAOTpF9JK2wBUJcNn4MSvlNtK7SZ9N72gB+ajHtA6D1abYXRcszZnBA4nHBwvFwzHw==

aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
@@ -2938,10 +2933,10 @@ boolbase@^1.0.0, boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=

bootstrap@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.0.tgz#97b9f29ac98f98dfa43bf7468262d84392552fd7"
integrity sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==
bootstrap@^5.0.0-beta3:
version "5.0.0-beta3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.0.0-beta3.tgz#c959f61fbd03667a1b158f763856994859d7a465"
integrity sha512-0urccjfIOzhrb9qJysN8XW/DRw6rg3zH7qLeKIp4Zyl8+Ens4JWB0NC0cB5AhnSFPd2tftRggjwCMxablo6Tpg==

brace-expansion@^1.1.7:
version "1.1.11"


Loading…
Cancel
Save