@@ -19,12 +19,7 @@ class Migration(migrations.Migration): | |||
operations = [ | |||
migrations.AddField( | |||
model_name='lesspassuser', | |||
name='has_password_profile_encrypted', | |||
field=models.BooleanField(default=False), | |||
), | |||
migrations.AddField( | |||
model_name='lesspassuser', | |||
name='encryted_key', | |||
name='key', | |||
field=models.TextField(null=True), | |||
), | |||
migrations.CreateModel( | |||
@@ -30,13 +30,12 @@ class LessPassUser(AbstractBaseUser): | |||
verbose_name='email address', max_length=255, unique=True) | |||
is_active = models.BooleanField(default=True) | |||
is_admin = models.BooleanField(default=False) | |||
has_password_profile_encrypted = models.BooleanField(default=False) | |||
encrypted_key = models.TextField(null=True) | |||
key = models.TextField(null=True) | |||
objects = LesspassUserManager() | |||
USERNAME_FIELD = 'email' | |||
REQUIRED_FIELDS = ['email', 'encrypted_key'] | |||
REQUIRED_FIELDS = ['email', 'key'] | |||
def get_full_name(self): | |||
return self.email | |||
@@ -38,9 +38,17 @@ function encrypt(data, password) { | |||
return new_data; | |||
} | |||
function decrypt(data, password) { | |||
var cipher = crypto.createDecipher('aes-128-cbc', password); | |||
var new_data = cipher.update(data, 'hex', 'utf8') | |||
new_data += cipher.final('utf8'); | |||
return new_data; | |||
} | |||
module.exports = { | |||
stringToArrayBuffer, | |||
arrayBufferToHex, | |||
getAlgorithm, | |||
encrypt | |||
encrypt, | |||
decrypt | |||
}; |
@@ -7,8 +7,8 @@ export default { | |||
getLoggedUserInformation() { | |||
return http.get('/api/auth/users/me'); | |||
}, | |||
patch({ encryptedKey }) { | |||
return http.patch('/api/auth/users/me', { encryptedKey }); | |||
patch({ key }) { | |||
return http.patch('/api/auth/users/me', { key }); | |||
}, | |||
register({ email, password }) { | |||
return http.post("/api/auth/users/", { email, password }); | |||
@@ -1,5 +1,6 @@ | |||
import Password from "../api/password"; | |||
import Profile from "../api/profile"; | |||
import LessPassCrypto from "lesspass-crypto"; | |||
import * as urlParser from "../services/url-parser"; | |||
import * as types from "./mutation-types"; | |||
import defaultPasswordProfile from "./defaultPassword"; | |||
@@ -42,22 +43,22 @@ export const logout = ({ commit }) => { | |||
commit(types.RESET_PASSWORD); | |||
}; | |||
export const getPasswords = ({ commit }) => { | |||
Profile.all().then(response => { | |||
let encryptedProfiles = response.data.results; | |||
if (encryptedProfiles.length > 0) { | |||
encryptedProfiles = encryptedProfiles[0]; | |||
console.log(encryptedProfiles.password_profile); | |||
} | |||
}); | |||
return Password.all() | |||
.then(response => { | |||
export const getPasswords = ({ commit }, { key, password }) => { | |||
return Profile.all().then(response => { | |||
if (response.data.results.length > 0) { | |||
const encryptedPasswordProfiles = response.data.results[0].password_profile; | |||
const encryptedKey = LessPassCrypto.encrypt( | |||
key, | |||
password | |||
); | |||
const passwords = JSON.parse( | |||
LessPassCrypto.decrypt(encryptedPasswordProfiles, encryptedKey) | |||
); | |||
commit(types.LOGIN); | |||
const passwords = response.data.results; | |||
commit(types.SET_PASSWORDS, { passwords }); | |||
return passwords; | |||
}) | |||
.catch(() => logout({ commit })); | |||
return | |||
} | |||
}).catch(() => logout({ commit }));; | |||
}; | |||
export const saveOrUpdatePassword = ({ commit, state }) => { | |||
@@ -114,9 +114,9 @@ export default { | |||
User.login({ email: this.email, password: this.password }) | |||
.then(response => { | |||
User.getLoggedUserInformation().then(response => { | |||
if (response.data.encrypted_key === null) { | |||
if (response.data.key === null) { | |||
LessPassEntropy.generateUserKey().then(key => { | |||
const encrypted_key = LessPassCrypto.encrypt( | |||
const encryptedKey = LessPassCrypto.encrypt( | |||
key, | |||
this.password | |||
); | |||
@@ -137,16 +137,24 @@ export default { | |||
const data = JSON.stringify(allPasswords); | |||
const encryptedPasswordProfiles = LessPassCrypto.encrypt( | |||
data, | |||
key | |||
encryptedKey | |||
); | |||
Profile.create({ | |||
password_profile: encryptedPasswordProfiles | |||
}).then(() => { | |||
User.patch({ key }); | |||
this.$store.dispatch("getPasswords", { | |||
key: key, | |||
password: this.password | |||
}); | |||
}); | |||
User.patch({ encrypted_key }); | |||
}); | |||
}); | |||
} else { | |||
console.log("user has encrypted key"); | |||
this.$store.dispatch("getPasswords", { | |||
key: response.data.key, | |||
password: this.password | |||
}); | |||
} | |||
}); | |||
this.$store.dispatch("login", response.data); | |||
@@ -12,7 +12,11 @@ div.awesomplete > ul { | |||
} | |||
</style> | |||
<template> | |||
<form id="password-generator" v-on:submit.prevent="generatePassword" novalidate> | |||
<form | |||
id="password-generator" | |||
v-on:submit.prevent="generatePassword" | |||
novalidate | |||
> | |||
<div class="form-group"> | |||
<input-site | |||
ref="site" | |||
@@ -25,7 +29,7 @@ div.awesomplete > ul { | |||
</div> | |||
<remove-auto-complete></remove-auto-complete> | |||
<div class="form-group"> | |||
<label for="login" class="sr-only">{{ $t('Login') }}</label> | |||
<label for="login" class="sr-only">{{ $t("Login") }}</label> | |||
<div class="inner-addon left-addon"> | |||
<i class="fa fa-user"></i> | |||
<input | |||
@@ -59,7 +63,9 @@ div.awesomplete > ul { | |||
tabindex="0" | |||
class="btn btn-primary btn-block" | |||
v-if="!passwordGenerated" | |||
>{{ $t('Generate') }}</button> | |||
> | |||
{{ $t("Generate") }} | |||
</button> | |||
<div class="input-group" v-show="passwordGenerated"> | |||
<span class="input-group-btn"> | |||
<button | |||
@@ -128,16 +134,14 @@ export default { | |||
}, | |||
computed: { | |||
...mapState(["password", "passwords"]), | |||
...mapGetters(["passwordURL"]), | |||
...mapGetters(["passwordURL"]) | |||
}, | |||
beforeMount() { | |||
this.$store.dispatch("getPasswords").then(() => { | |||
urlParser.getSite().then(site => { | |||
this.$store.dispatch("loadPasswordProfile", { site }); | |||
}); | |||
this.$store.dispatch("getPasswordFromUrlQuery", { | |||
query: this.$route.query | |||
}); | |||
urlParser.getSite().then(site => { | |||
this.$store.dispatch("loadPasswordProfile", { site }); | |||
}); | |||
this.$store.dispatch("getPasswordFromUrlQuery", { | |||
query: this.$route.query | |||
}); | |||
}, | |||
mounted() { | |||
@@ -112,7 +112,9 @@ export default { | |||
var siteMatch = password.site.match(new RegExp(this.searchQuery, "i")); | |||
return loginMatch || siteMatch; | |||
}); | |||
this.pagination.pageCount = Math.ceil(passwords.length / this.pagination.perPage); | |||
this.pagination.pageCount = Math.ceil( | |||
passwords.length / this.pagination.perPage | |||
); | |||
return passwords.slice( | |||
this.pagination.currentPage * this.pagination.perPage - | |||
this.pagination.perPage, | |||
@@ -120,9 +122,6 @@ export default { | |||
); | |||
} | |||
}, | |||
beforeMount() { | |||
this.$store.dispatch("getPasswords"); | |||
}, | |||
methods: { | |||
setCurrentPage(page) { | |||
this.pagination.currentPage = page; | |||