mirror of https://github.com/lissy93/dashy
211 lines
7.6 KiB
JavaScript
211 lines
7.6 KiB
JavaScript
import sha256 from 'crypto-js/sha256';
|
|
import ConfigAccumulator from '@/utils/ConfigAccumalator';
|
|
import ErrorHandler from '@/utils/ErrorHandler';
|
|
import { cookieKeys, localStorageKeys, userStateEnum } from '@/utils/defaults';
|
|
import { isKeycloakEnabled } from '@/utils/KeycloakAuth';
|
|
|
|
/* Uses config accumulator to get and return app config */
|
|
const getAppConfig = () => {
|
|
const Accumulator = new ConfigAccumulator();
|
|
const config = Accumulator.config();
|
|
return config.appConfig || {};
|
|
};
|
|
|
|
/**
|
|
* Called when the user is still using array for users, prints warning
|
|
* This was a breaking change, implemented in V 1.6.5
|
|
* Support for old user structure will be removed in V 1.7.0
|
|
*/
|
|
const printWarning = () => {
|
|
ErrorHandler('From V 1.6.5 onwards, the structure of the users object has changed.');
|
|
};
|
|
|
|
/* Returns array of users from appConfig.auth, if available, else an empty array */
|
|
const getUsers = () => {
|
|
const appConfig = getAppConfig();
|
|
const auth = appConfig.auth || {};
|
|
// Check if the user is still using previous schema type
|
|
if (Array.isArray(auth)) {
|
|
printWarning(); // Print warning message
|
|
return []; // Support for old data structure now removed
|
|
}
|
|
// Otherwise, return the users array, if available
|
|
return auth.users || [];
|
|
};
|
|
|
|
/**
|
|
* Generates a 1-way hash, in order to be stored in local storage for authentication
|
|
* @param {String} user The username of user
|
|
* @returns {String} The hashed token
|
|
*/
|
|
const generateUserToken = (user) => {
|
|
if (!user.user || !user.hash) {
|
|
ErrorHandler('Invalid user object. Must have `user` and `hash` parameters');
|
|
return undefined;
|
|
}
|
|
const strAndUpper = (input) => input.toString().toUpperCase();
|
|
const sha = sha256(strAndUpper(user.user) + strAndUpper(user.hash));
|
|
return strAndUpper(sha);
|
|
};
|
|
|
|
/**
|
|
* Checks if the user is currently authenticated
|
|
* @returns {Boolean} Will return true if the user is logged in, else false
|
|
*/
|
|
export const isLoggedIn = () => {
|
|
const users = getUsers();
|
|
const validTokens = users.map((user) => generateUserToken(user));
|
|
let userAuthenticated = false;
|
|
document.cookie.split(';').forEach((cookie) => {
|
|
if (cookie && cookie.split('=').length > 1) {
|
|
const cookieKey = cookie.split('=')[0].trim();
|
|
const cookieValue = cookie.split('=')[1].trim();
|
|
if (cookieKey === cookieKeys.AUTH_TOKEN) {
|
|
if (validTokens.includes(cookieValue)) {
|
|
userAuthenticated = true;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return userAuthenticated;
|
|
};
|
|
|
|
/* Returns true if authentication is enabled */
|
|
export const isAuthEnabled = () => {
|
|
const users = getUsers();
|
|
return (users.length > 0);
|
|
};
|
|
|
|
/* Returns true if guest access is enabled */
|
|
export const isGuestAccessEnabled = () => {
|
|
const appConfig = getAppConfig();
|
|
if (appConfig.auth && typeof appConfig.auth === 'object' && !isKeycloakEnabled()) {
|
|
return appConfig.auth.enableGuestAccess || false;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Checks credentials entered by the user against those in the config
|
|
* Returns an object containing a boolean indicating success/ failure
|
|
* along with a message outlining what's not right
|
|
* @param {String} username The username entered by the user
|
|
* @param {String} pass The password entered by the user
|
|
* @param {String[]} users An array of valid user objects
|
|
* @param {Object} messages A static message template object
|
|
* @returns {Object} An object containing a boolean result and a message
|
|
*/
|
|
export const checkCredentials = (username, pass, users, messages) => {
|
|
let response; // Will store an object containing boolean and message
|
|
if (!username) {
|
|
response = { correct: false, msg: messages.missingUsername };
|
|
} else if (!pass) {
|
|
response = { correct: false, msg: messages.missingPassword };
|
|
} else {
|
|
users.forEach((user) => {
|
|
if (user.user.toLowerCase() === username.toLowerCase()) { // User found
|
|
if (user.hash.toLowerCase() === sha256(pass).toString().toLowerCase()) {
|
|
response = { correct: true, msg: messages.successMsg }; // Password is correct
|
|
} else { // User found, but password is not a match
|
|
response = { correct: false, msg: messages.incorrectPassword };
|
|
}
|
|
}
|
|
});
|
|
}
|
|
return response || { correct: false, msg: messages.incorrectUsername };
|
|
};
|
|
|
|
/**
|
|
* Sets the cookie value in order to login the user locally
|
|
* @param {String} username - The users username
|
|
* @param {String} pass - Password, not yet hashed
|
|
* @param {Number} timeout - A desired timeout for the session, in ms
|
|
*/
|
|
export const login = (username, pass, timeout) => {
|
|
const now = new Date();
|
|
const expiry = new Date(now.setTime(now.getTime() + timeout)).toGMTString();
|
|
const userObject = { user: username, hash: sha256(pass).toString().toLowerCase() };
|
|
document.cookie = `authenticationToken=${generateUserToken(userObject)};`
|
|
+ `${timeout > 0 ? `expires=${expiry}` : ''}`;
|
|
localStorage.setItem(localStorageKeys.USERNAME, username);
|
|
};
|
|
|
|
/**
|
|
* Removed the browsers' cookie, causing user to be logged out
|
|
*/
|
|
export const logout = () => {
|
|
document.cookie = 'authenticationToken=null';
|
|
localStorage.removeItem(localStorageKeys.USERNAME);
|
|
};
|
|
|
|
/**
|
|
* If correctly logged in as a valid, authenticated user,
|
|
* then returns the user object for the current user
|
|
* If not logged in, will return false
|
|
* */
|
|
export const getCurrentUser = () => {
|
|
if (!isLoggedIn()) return false; // User not logged in
|
|
const username = localStorage[localStorageKeys.USERNAME]; // Get username
|
|
if (!username) return false; // No username
|
|
let foundUserObject = false; // Value to return
|
|
getUsers().forEach((user) => {
|
|
// If current logged-in user found, then return that user
|
|
if (user.user === username) foundUserObject = user;
|
|
});
|
|
return foundUserObject;
|
|
};
|
|
|
|
/**
|
|
* Checks if the user is viewing the dashboard as a guest
|
|
* Returns true if guest mode enabled, and user not logged in
|
|
* */
|
|
export const isLoggedInAsGuest = () => {
|
|
const guestEnabled = isGuestAccessEnabled();
|
|
const notLoggedIn = !isLoggedIn();
|
|
return guestEnabled && notLoggedIn;
|
|
};
|
|
|
|
/**
|
|
* Checks if the current user has admin privileges.
|
|
* If no users are set up, then function will always return true
|
|
* But if auth is configured, then will verify user is correctly
|
|
* logged in and then check weather they are of type admin, and
|
|
* return false if any conditions fail
|
|
* @returns {Boolean} - True if admin privileges
|
|
*/
|
|
export const isUserAdmin = () => {
|
|
const users = getUsers();
|
|
if (users.length === 0) return true; // Authentication not setup
|
|
if (!isLoggedIn()) return false; // Auth setup, but not signed in as a valid user
|
|
const currentUser = localStorage[localStorageKeys.USERNAME];
|
|
let isAdmin = false;
|
|
users.forEach((user) => {
|
|
if (user.user === currentUser) {
|
|
if (user.type === 'admin') isAdmin = true;
|
|
}
|
|
});
|
|
return isAdmin;
|
|
};
|
|
|
|
/**
|
|
* Determines which button should display, based on the user type
|
|
* 0 = Auth not configured (don't show anything)
|
|
* 1 = Auth configured, and user logged in (show logout button)
|
|
* 2 = Auth configured, guest access enabled, not logged in (show login)
|
|
* Note that if auth is enabled, but not guest access, and user not logged in,
|
|
* then they will never be able to view the homepage, so no button needed
|
|
*/
|
|
export const getUserState = () => {
|
|
const {
|
|
notConfigured,
|
|
loggedIn,
|
|
guestAccess,
|
|
keycloakEnabled,
|
|
} = userStateEnum; // Numeric enum options
|
|
if (isKeycloakEnabled()) return keycloakEnabled; // Keycloak auth configured
|
|
if (!isAuthEnabled()) return notConfigured; // No auth enabled
|
|
if (isLoggedIn()) return loggedIn; // User is logged in
|
|
if (isGuestAccessEnabled()) return guestAccess; // Guest is viewing
|
|
return notConfigured;
|
|
};
|