ampache_react/app/actions/auth.js
Phyks (Lucas Verney) 9717bdc47b Store invalidation on logout
Invalidate the store at logout, emptying cached items such as artists,
albums and songs and then preventing them from quickly reappearing when
reconnecting with the same or a different account.

Closes #5.
2016-08-03 15:55:42 +02:00

178 lines
5.2 KiB
JavaScript

import { push } from "react-router-redux";
import jsSHA from "jssha";
import Cookies from "js-cookie";
import { CALL_API } from "../middleware/api";
import { invalidateStore } from "./store";
import { i18nRecord } from "../models/i18n";
export const DEFAULT_SESSION_INTERVAL = 1800 * 1000; // 30 mins default
function _cleanEndpoint (endpoint) {
// Handle endpoints of the form "ampache.example.com"
if (
!endpoint.startsWith("//") &&
!endpoint.startsWith("http://") &&
!endpoint.startsWith("https://"))
{
endpoint = window.location.protocol + "//" + endpoint;
}
// Remove trailing slash and store endpoint
endpoint = endpoint.replace(/\/$/, "");
return endpoint;
}
function _buildHMAC (password) {
// Handle Ampache HMAC generation
const time = Math.floor(Date.now() / 1000);
var shaObj = new jsSHA("SHA-256", "TEXT");
shaObj.update(password);
const key = shaObj.getHash("HEX");
shaObj = new jsSHA("SHA-256", "TEXT");
shaObj.update(time + key);
return {
time: time,
passphrase: shaObj.getHash("HEX")
};
}
export function loginKeepAlive(username, token, endpoint) {
return {
type: CALL_API,
payload: {
endpoint: endpoint,
dispatch: [
null,
null,
error => dispatch => {
dispatch(loginUserFailure(error || new i18nRecord({ id: "app.login.expired", values: {}})));
}
],
action: "ping",
auth: token,
username: username,
extraParams: {}
}
};
}
export const LOGIN_USER_SUCCESS = "LOGIN_USER_SUCCESS";
export function loginUserSuccess(username, token, endpoint, rememberMe, timerID) {
return {
type: LOGIN_USER_SUCCESS,
payload: {
username: username,
token: token,
endpoint: endpoint,
rememberMe: rememberMe,
timerID: timerID
}
};
}
export const LOGIN_USER_FAILURE = "LOGIN_USER_FAILURE";
export function loginUserFailure(error) {
Cookies.remove("username");
Cookies.remove("token");
Cookies.remove("endpoint");
return {
type: LOGIN_USER_FAILURE,
payload: {
error: error
}
};
}
export const LOGIN_USER_REQUEST = "LOGIN_USER_REQUEST";
export function loginUserRequest() {
return {
type: LOGIN_USER_REQUEST
};
}
export const LOGOUT_USER = "LOGOUT_USER";
export function logout() {
return (dispatch, state) => {
const { auth } = state();
if (auth.timerID) {
clearInterval(auth.timerID);
}
Cookies.remove("username");
Cookies.remove("token");
Cookies.remove("endpoint");
dispatch({
type: LOGOUT_USER
});
};
}
export function logoutAndRedirect() {
return (dispatch) => {
dispatch(logout());
dispatch(invalidateStore());
dispatch(push("/login"));
};
}
export function loginUser(username, passwordOrToken, endpoint, rememberMe, redirect="/", isToken=false) {
endpoint = _cleanEndpoint(endpoint);
var time = 0;
var passphrase = passwordOrToken;
if (!isToken) {
// Standard password connection
const HMAC = _buildHMAC(passwordOrToken);
time = HMAC.time;
passphrase = HMAC.passphrase;
} else {
// Remember me connection
if (passwordOrToken.expires < new Date()) {
// Token has expired
return loginUserFailure("app.login.expired");
}
time = Math.floor(Date.now() / 1000);
passphrase = passwordOrToken.token;
}
return {
type: CALL_API,
payload: {
endpoint: endpoint,
dispatch: [
loginUserRequest,
jsonData => dispatch => {
if (!jsonData.auth || !jsonData.sessionExpire) {
return dispatch(loginUserFailure(new i18nRecord({ id: "app.api.error", values: {} })));
}
const token = {
token: jsonData.auth,
expires: new Date(jsonData.sessionExpire)
};
// Dispatch success
const timerID = setInterval(
() => dispatch(loginKeepAlive(username, token.token, endpoint)),
DEFAULT_SESSION_INTERVAL
);
if (rememberMe) {
const cookiesOption = { expires: token.expires };
Cookies.set("username", username, cookiesOption);
Cookies.set("token", token, cookiesOption);
Cookies.set("endpoint", endpoint, cookiesOption);
}
dispatch(loginUserSuccess(username, token, endpoint, rememberMe, timerID));
// Redirect
dispatch(push(redirect));
},
loginUserFailure
],
action: "handshake",
auth: passphrase,
username: username,
extraParams: {timestamp: time}
}
};
}