ampache_react/app/actions/auth.js

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);
let 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);
let time = 0;
let 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}
}
};
}