2016-07-07 23:23:18 +02:00
|
|
|
import { push } from "react-router-redux";
|
|
|
|
import jsSHA from "jssha";
|
|
|
|
import Cookies from "js-cookie";
|
|
|
|
|
|
|
|
import { CALL_API } from "../middleware/api";
|
|
|
|
|
|
|
|
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://"))
|
|
|
|
{
|
2016-07-28 23:57:29 +02:00
|
|
|
endpoint = window.location.protocol + "//" + endpoint;
|
2016-07-07 23:23:18 +02:00
|
|
|
}
|
|
|
|
// 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 || "Your session expired… =("));
|
|
|
|
}
|
|
|
|
],
|
|
|
|
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(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("Your session 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 Promise.reject("API error.");
|
|
|
|
}
|
|
|
|
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}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|