Phyks (Lucas Verney)
d8a7d4f66a
Full rework of webplayer. Webplayer is back to its previous working state, and ready for further improvements.
254 lines
7.2 KiB
JavaScript
254 lines
7.2 KiB
JavaScript
/**
|
|
* This file implements authentication related actions.
|
|
*/
|
|
|
|
// NPM imports
|
|
import { push } from "react-router-redux";
|
|
import Cookies from "js-cookie";
|
|
|
|
// Local imports
|
|
import { buildHMAC, cleanURL } from "../utils";
|
|
|
|
// Models
|
|
import { i18nRecord } from "../models/i18n";
|
|
|
|
// Other actions and payload types
|
|
import { CALL_API } from "../middleware/api";
|
|
import { invalidateStore } from "./store";
|
|
|
|
|
|
// Constants
|
|
export const DEFAULT_SESSION_INTERVAL = 1800 * 1000; // 30 mins long sessoins by default
|
|
|
|
|
|
/**
|
|
* Dispatch a ping query to the API for login keepalive and prevent session
|
|
* from expiring.
|
|
*
|
|
* @param username Username to use
|
|
* @param token Token to revive
|
|
* @param endpoint Ampache base URL
|
|
*
|
|
* @return A CALL_API payload to keep session alive.
|
|
*/
|
|
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";
|
|
/**
|
|
* Action to be called on successful login.
|
|
*
|
|
* @param username Username used for login
|
|
* @param token Token got back from the API
|
|
* @param endpoint Ampache server base URL
|
|
* @param rememberMe Whether to remember me or not
|
|
* @param timerID ID of the timer set for session keepalive.
|
|
*
|
|
* @return A login success payload.
|
|
*/
|
|
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";
|
|
/**
|
|
* Action to be called on failed login.
|
|
*
|
|
* This action removes any remember me cookie if any was set.
|
|
*
|
|
* @param error An error object, either string or i18nRecord.
|
|
* @return A login failure payload.
|
|
*/
|
|
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_EXPIRED = "LOGIN_USER_EXPIRED";
|
|
/**
|
|
* Action to be called when session is expired.
|
|
*
|
|
* @param error An error object, either a string or i18nRecord.
|
|
* @return A session expired payload.
|
|
*/
|
|
export function loginUserExpired(error) {
|
|
return {
|
|
type: LOGIN_USER_EXPIRED,
|
|
payload: {
|
|
error: error,
|
|
},
|
|
};
|
|
}
|
|
|
|
|
|
export const LOGIN_USER_REQUEST = "LOGIN_USER_REQUEST";
|
|
/**
|
|
* Action to be called when login is requested.
|
|
*
|
|
* @return A login request payload.
|
|
*/
|
|
export function loginUserRequest() {
|
|
return {
|
|
type: LOGIN_USER_REQUEST,
|
|
};
|
|
}
|
|
|
|
|
|
export const LOGOUT_USER = "LOGOUT_USER";
|
|
/**
|
|
* Action to be called upon logout.
|
|
*
|
|
* This function clears the cookies set for remember me and the keep alive
|
|
* timer.
|
|
*
|
|
* @remark This function does not clear the other stores, nor handle
|
|
* redirection.
|
|
*
|
|
* @return A logout payload.
|
|
*/
|
|
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,
|
|
});
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
* Action to be called to log a user out.
|
|
*
|
|
* This function clears the remember me cookies and the keepalive timer. It
|
|
* also clears the data behind authentication in the store and redirects to
|
|
* login page.
|
|
*/
|
|
export function logoutAndRedirect() {
|
|
return (dispatch) => {
|
|
dispatch(logout());
|
|
dispatch(invalidateStore());
|
|
dispatch(push("/login"));
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
* Action to be called to log a user in.
|
|
*
|
|
* @param username Username to use.
|
|
* @param passwordOrToken User password, or previous token to revive.
|
|
* @param endpoint Ampache server base URL.
|
|
* @param rememberMe Whether to rememberMe or not
|
|
* @param[optional] redirect Page to redirect to after login.
|
|
* @param[optional] isToken Whether passwordOrToken is a password or a
|
|
* token.
|
|
*
|
|
* @return A CALL_API payload to perform login.
|
|
*/
|
|
export function loginUser(username, passwordOrToken, endpoint, rememberMe, redirect="/", isToken=false) {
|
|
// Clean endpoint
|
|
endpoint = cleanURL(endpoint);
|
|
|
|
// Get passphrase and time parameters
|
|
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) {
|
|
// On success, check that we are actually authenticated
|
|
return dispatch(loginUserFailure(new i18nRecord({ id: "app.api.error", values: {} })));
|
|
}
|
|
// Get token from the API
|
|
const token = {
|
|
token: jsonData.auth,
|
|
expires: new Date(jsonData.sessionExpire),
|
|
};
|
|
// Handle session keep alive timer
|
|
const timerID = setInterval(
|
|
() => dispatch(loginKeepAlive(username, token.token, endpoint)),
|
|
DEFAULT_SESSION_INTERVAL
|
|
);
|
|
if (rememberMe) {
|
|
// Handle remember me option
|
|
const cookiesOption = { expires: token.expires };
|
|
Cookies.set("username", username, cookiesOption);
|
|
Cookies.set("token", token, cookiesOption);
|
|
Cookies.set("endpoint", endpoint, cookiesOption);
|
|
}
|
|
// Dispatch login success
|
|
dispatch(loginUserSuccess(username, token, endpoint, rememberMe, timerID));
|
|
// Redirect
|
|
dispatch(push(redirect));
|
|
},
|
|
loginUserFailure,
|
|
],
|
|
action: "handshake",
|
|
auth: passphrase,
|
|
username: username,
|
|
extraParams: {timestamp: time},
|
|
},
|
|
};
|
|
}
|