@@ -1,6 +1,6 @@ | |||
{ | |||
"name": "lesspass-pure", | |||
"version": "9.1.9", | |||
"version": "9.1.10", | |||
"description": "LessPass web component", | |||
"license": "GPL-3.0", | |||
"author": "Guillaume Vincent <guillaume@oslab.fr>", | |||
@@ -80,7 +80,6 @@ export default { | |||
}, | |||
created() { | |||
this.$store.dispatch("cleanMessage"); | |||
this.$store.dispatch("refreshToken"); | |||
this.$store.dispatch("resetPassword"); | |||
} | |||
}; | |||
@@ -4,7 +4,7 @@ export default { | |||
addAuthorizationHeader(config) { | |||
return { | |||
...config, | |||
headers: { Authorization: `JWT ${config.token}` } | |||
headers: { Authorization: `Bearer ${config.access_token}` } | |||
}; | |||
}, | |||
all(config) { | |||
@@ -4,7 +4,7 @@ import Passwords from "./password"; | |||
const mock = new MockAdapter(axios); | |||
const config = { baseURL: "https://lesspass.com", token: "abc" }; | |||
const config = { baseURL: "https://lesspass.com", access_token: "abc" }; | |||
test("Passwords.create", () => { | |||
const password = { login: "text@example.org" }; | |||
@@ -1,25 +1,25 @@ | |||
import axios from "axios"; | |||
export default { | |||
login(user, config) { | |||
return axios.post("/api/tokens/auth/", user, config).then(response => { | |||
return response.data; | |||
}); | |||
login({ email, password }, config) { | |||
return axios.post("/api/auth/jwt/create/", { email, password }, config); | |||
}, | |||
register(user, config) { | |||
return axios.post("/api/auth/register/", user, config).then(response => { | |||
return response.data; | |||
}); | |||
register({ email, password }, config) { | |||
return axios.post("/api/auth/users/", { email, password }, config); | |||
}, | |||
resetPassword(email, config) { | |||
return axios.post("/api/auth/password/reset/", email, config); | |||
resetPassword({ email }, config) { | |||
return axios.post("/api/auth/users/reset_password/", { email }, config); | |||
}, | |||
confirmResetPassword(password, config) { | |||
return axios.post("/api/auth/password/reset/confirm/", password, config); | |||
}, | |||
requestNewToken(token, config) { | |||
return axios.post("/api/tokens/refresh/", token, config).then(response => { | |||
return response.data.token; | |||
}); | |||
confirmResetPassword({ uid, token, password }, config) { | |||
return axios.post( | |||
"/api/auth/users/reset_password_confirm/", | |||
{ | |||
uid, | |||
token, | |||
new_password: password, | |||
re_new_password: password | |||
}, | |||
config | |||
); | |||
} | |||
}; |
@@ -5,40 +5,42 @@ import User from "./user"; | |||
const mock = new MockAdapter(axios); | |||
test("login", () => { | |||
const token = "5e0651"; | |||
const access = "12345"; | |||
const refresh = "67890" | |||
const user = { email: "test@example.org", password: "password" }; | |||
mock | |||
.onPost("/api/tokens/auth/", user) | |||
.reply(201, { token }); | |||
.onPost("/api/auth/jwt/create/", user) | |||
.reply(201, { access, refresh }); | |||
return User.login(user, { | |||
baseURL: "https://lesspass.com" | |||
}).then(response => { | |||
expect(response.token).toBe(token); | |||
expect(response.data.access).toBe(access); | |||
expect(response.data.refresh).toBe(refresh); | |||
}); | |||
}); | |||
test("register", () => { | |||
const user = { email: "test@example.org", password: "password" }; | |||
mock | |||
.onPost("/api/auth/register/", user) | |||
.onPost("/api/auth/users/", user) | |||
.reply(201, { email: user.email, pk: 1 }); | |||
return User.register(user, { | |||
baseURL: "https://lesspass.com" | |||
}).then(response => { | |||
expect(response.email).toBe(user.email); | |||
expect(response.data.email).toBe(user.email); | |||
}); | |||
}); | |||
test("resetPassword", () => { | |||
var email = "test@lesspass.com"; | |||
mock | |||
.onPost("/api/auth/password/reset/", { email }) | |||
.onPost("/api/auth/users/reset_password/", { email }) | |||
.reply(204); | |||
return User.resetPassword( | |||
{ email }, | |||
{ baseURL: "https://lesspass.com" } | |||
).then(data => { | |||
expect(data.status).toBe(204); | |||
).then(response => { | |||
expect(response.status).toBe(204); | |||
}); | |||
}); | |||
@@ -46,29 +48,19 @@ test("confirmResetPassword", () => { | |||
var newPassword = { | |||
uid: "MQ", | |||
token: "5g1-2bd69bd6f6dcd73f8124", | |||
new_password: "password1" | |||
new_password: "password1", | |||
re_new_password: "password1", | |||
}; | |||
mock | |||
.onPost("/api/auth/password/reset/confirm/", newPassword) | |||
.onPost("/api/auth/users/reset_password_confirm/", newPassword) | |||
.reply(204); | |||
return User.confirmResetPassword(newPassword, { | |||
return User.confirmResetPassword({ | |||
uid: "MQ", | |||
token: "5g1-2bd69bd6f6dcd73f8124", | |||
password: "password1", | |||
}, { | |||
baseURL: "https://lesspass.com" | |||
}).then(data => { | |||
expect(data.status).toBe(204); | |||
}); | |||
}); | |||
test("refresh token", () => { | |||
const token = "3e3231"; | |||
const newToken = | |||
"wibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9eyJzdWIiOiIxMjM0NTY3ODkwIi"; | |||
mock | |||
.onPost("/api/tokens/refresh/", { token }) | |||
.reply(200, { token: newToken }); | |||
return User.requestNewToken( | |||
{ token }, | |||
{ baseURL: "https://lesspass.com" } | |||
).then(refreshedToken => { | |||
expect(refreshedToken).toBe(newToken); | |||
}).then(response => { | |||
expect(response.status).toBe(204); | |||
}); | |||
}); |
@@ -59,11 +59,11 @@ | |||
methods: { | |||
fullReload() { | |||
this.$store.dispatch('resetPassword'); | |||
this.$router.push({name: 'home'}); | |||
this.$router.push({name: 'home'}).catch(e => {}); | |||
}, | |||
logout() { | |||
this.$store.dispatch('logout'); | |||
this.$router.push({name: 'home'}); | |||
this.$router.push({name: 'home'}).catch(e => {}); | |||
}, | |||
saveOrUpdatePassword() { | |||
this.$store.dispatch('saveOrUpdatePassword'); | |||
@@ -1,18 +1,8 @@ | |||
import Password from "../api/password"; | |||
import User from "../api/user"; | |||
import * as urlParser from "../services/url-parser"; | |||
import * as types from "./mutation-types"; | |||
import defaultPasswordProfile from "./defaultPassword"; | |||
export const refreshToken = ({ commit, state }) => { | |||
const token = state.token; | |||
if (token) { | |||
User.requestNewToken({ token }, { baseURL: state.baseURL }) | |||
.then(newToken => commit(types.SET_TOKEN, { token: newToken })) | |||
.catch(() => commit(types.LOGOUT)); | |||
} | |||
}; | |||
export const saveDefaultOptions = ({ commit }, payload) => { | |||
commit(types.SET_DEFAULT_OPTIONS, payload); | |||
}; | |||
@@ -37,9 +27,12 @@ export const resetPassword = ({ commit }) => { | |||
commit(types.RESET_PASSWORD); | |||
}; | |||
export const login = ({ commit }, payload) => { | |||
commit(types.SET_BASE_URL, payload); | |||
commit(types.SET_TOKEN, payload); | |||
export const setBaseURL = ({ commit }, { baseURL }) => { | |||
commit(types.SET_BASE_URL, { baseURL }); | |||
}; | |||
export const login = ({ commit }, { access, refresh }) => { | |||
commit(types.SET_TOKENS, { access_token: access, refresh_token: refresh }); | |||
commit(types.LOGIN); | |||
}; | |||
@@ -15,7 +15,8 @@ const state = { | |||
message: "", | |||
defaultPassword: defaultPassword, | |||
showOptions: false, | |||
token: null, | |||
access_token: null, | |||
refresh_token: null, | |||
baseURL: "https://lesspass.com" | |||
}; | |||
@@ -27,7 +28,7 @@ export default new Vuex.Store({ | |||
plugins: [ | |||
createPersistedState({ | |||
key: "lesspass", | |||
paths: ["token", "baseURL", "authenticated", "defaultPassword"] | |||
paths: ["access_token", "refresh_token", "baseURL", "authenticated", "defaultPassword"] | |||
}) | |||
] | |||
}); |
@@ -5,7 +5,7 @@ export const SET_DEFAULT_OPTIONS = "SET_DEFAULT_OPTIONS"; | |||
export const SET_MESSAGE = "SET_MESSAGE"; | |||
export const SET_PASSWORD = "SET_PASSWORD"; | |||
export const SET_PASSWORDS = "SET_PASSWORDS"; | |||
export const SET_TOKEN = "SET_TOKEN"; | |||
export const SET_TOKENS = "SET_TOKENS"; | |||
export const RESET_PASSWORD = "RESET_PASSWORD"; | |||
export const SET_SITE = "SET_SITE"; | |||
export const LOAD_PASSWORD_PROFILE = "LOAD_PASSWORD_PROFILE"; | |||
@@ -4,8 +4,9 @@ export default { | |||
[types.LOGIN](state) { | |||
state.authenticated = true; | |||
}, | |||
[types.SET_TOKEN](state, { token }) { | |||
state.token = token; | |||
[types.SET_TOKENS](state, { refresh_token, access_token }) { | |||
state.refresh_token = refresh_token; | |||
state.access_token = access_token | |||
}, | |||
[types.LOGOUT](state) { | |||
state.authenticated = false; | |||
@@ -43,12 +43,14 @@ test("LOGIN", () => { | |||
expect(state.authenticated).toBe(true); | |||
}); | |||
test("SET_TOKEN", () => { | |||
const token = "123456"; | |||
const SET_TOKEN = mutations[types.SET_TOKEN]; | |||
test("SET_TOKENS", () => { | |||
const access_token = "123456"; | |||
const refresh_token = "7890" | |||
const SET_TOKENS = mutations[types.SET_TOKENS]; | |||
const state = { token: null }; | |||
SET_TOKEN(state, { token }); | |||
expect(state.token).toBe(token); | |||
SET_TOKENS(state, { access_token, refresh_token }); | |||
expect(state.access_token).toBe(access_token); | |||
expect(state.refresh_token).toBe(refresh_token); | |||
}); | |||
test("SET_PASSWORD", () => { | |||
@@ -107,7 +107,8 @@ export default { | |||
const baseURL = this.baseURL; | |||
User.login({ email: this.email, password: this.password }, { baseURL }) | |||
.then(response => { | |||
this.$store.dispatch("login", { token: response.token, baseURL }); | |||
this.$store.dispatch("login", response.data); | |||
this.$store.dispatch("setBaseURL", { baseURL }); | |||
this.$router.push({ name: "home" }); | |||
}) | |||
.catch(err => { | |||
@@ -4,12 +4,14 @@ | |||
<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"> | |||
<input | |||
id="email" | |||
class="form-control" | |||
name="email" | |||
type="email" | |||
placeholder="Email" | |||
v-model="email" | |||
/> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -20,56 +22,73 @@ | |||
v-bind:label="$t('Master Password')" | |||
v-bind:email="email" | |||
v-bind:showEncryptButton="true" | |||
v-bind:EncryptButtonText="$t('Encrypt my master password')"></master-password> | |||
v-bind:EncryptButtonText="$t('Encrypt my master password')" | |||
></master-password> | |||
</div> | |||
</div> | |||
<div class="form-group row"> | |||
<div class="col-12"> | |||
<button id="loginButton" class="btn btn-primary"> | |||
{{$t('Reset my password')}} | |||
{{ $t("Reset my password") }} | |||
</button> | |||
</div> | |||
</div> | |||
</form> | |||
</template> | |||
<script type="text/ecmascript-6"> | |||
import User from '../api/user'; | |||
import message from '../services/message'; | |||
import MasterPassword from '../components/MasterPassword.vue'; | |||
import User from '../api/user'; | |||
import message from '../services/message'; | |||
import MasterPassword from '../components/MasterPassword.vue'; | |||
import { mapState } from "vuex"; | |||
export default { | |||
components: { | |||
MasterPassword | |||
}, | |||
data() { | |||
return { | |||
email: '', | |||
password: '' | |||
}; | |||
}, | |||
methods: { | |||
resetPasswordConfirm(){ | |||
if (!this.password) { | |||
message.error(this.$t('PasswordResetRequired', 'A password is required')); | |||
return; | |||
} | |||
User | |||
.confirmResetPassword({ | |||
export default { | |||
components: { | |||
MasterPassword | |||
}, | |||
data() { | |||
return { | |||
email: '', | |||
password: '' | |||
}; | |||
}, | |||
computed: mapState([ | |||
'baseURL' | |||
]), | |||
methods: { | |||
resetPasswordConfirm(){ | |||
if (!this.password) { | |||
message.error(this.$t('PasswordResetRequired', 'A password is required')); | |||
return; | |||
} | |||
User | |||
.confirmResetPassword( | |||
{ | |||
uid: this.$route.params.uid, | |||
token: this.$route.params.token, | |||
new_password: this.password | |||
}) | |||
.then(() => { | |||
message.success(this.$t('PasswordResetSuccessful', 'Your password was reset successfully.')); | |||
}) | |||
.catch(err => { | |||
if (err.response.status === 400) { | |||
message.error(this.$t('ResetLinkExpired', 'This password reset link has expired.')); | |||
} else { | |||
message.displayGenericError(); | |||
} | |||
}); | |||
} | |||
password: this.password | |||
}, | |||
{ | |||
baseURL: this.baseURL | |||
} | |||
) | |||
.then(() => { | |||
message.success(this.$t('PasswordResetSuccessful', 'Your password was reset successfully.')); | |||
User | |||
.login({ email: this.email, password: this.password }, { baseURL: this.baseURL }) | |||
.then(response => { | |||
this.$store.dispatch("login", response.data); | |||
this.$router.push({ name: "home" }); | |||
}) | |||
.catch(err => message.displayGenericError()); | |||
}) | |||
.catch(err => { | |||
if (err.response.status === 400) { | |||
message.error(this.$t('ResetLinkExpired', 'This password reset link has expired.')); | |||
} else { | |||
message.displayGenericError(); | |||
} | |||
}); | |||
} | |||
} | |||
} | |||
</script> |