From a95c0fb8cce8030d88038cf6c157c95a01d65756 Mon Sep 17 00:00:00 2001 From: Chaitanya Date: Sat, 17 Aug 2019 00:31:55 +0530 Subject: [PATCH] Login: Auto login when run through the rclone cli. Login: Auto login when run through the rclone cli. Login: Auto login when run through the rclone cli. --- src/actions/types.js | 3 +- src/actions/userActions.js | 16 ++++- src/containers/DefaultLayout/DefaultLayout.js | 4 +- src/reducers/explorerStateReducer.js | 10 --- src/reducers/userActionsReducer.js | 18 ++--- src/reducers/userActionsReducer.test.js | 4 +- src/utils/API/API.js | 8 ++- src/utils/Constants.js | 1 + src/views/Explorer/RemotesList/RemotesList.js | 8 +-- src/views/Pages/Login/Login.js | 70 ++++++++++++++++--- src/views/Pages/Login/Login.test.js | 2 +- .../Login/__snapshots__/Login.test.js.snap | 2 +- 12 files changed, 100 insertions(+), 46 deletions(-) diff --git a/src/actions/types.js b/src/actions/types.js index 019f78a57..bde7caa77 100644 --- a/src/actions/types.js +++ b/src/actions/types.js @@ -22,7 +22,8 @@ export const GET_STATUS_FOR_RUNNING_JOB = 'GET_STATUS_FOR_RUNNING_JOB'; export const SET_BANDWIDTH = 'SET_BANDWIDTH'; export const GET_BANDWIDTH = 'GET_BANDWIDTH'; export const ENABLE_STATUS_CHECK = 'ENABLE_STATUS_CHECK'; -export const CHANGE_USER_NAME_PASSWORD = 'CHANGE_USER_NAME_PASSWORD'; +// export const CHANGE_USER_NAME_PASSWORD = 'CHANGE_USER_NAME_PASSWORD'; +export const CHANGE_AUTH_KEY = 'CHANGE_AUTH_KEY'; export const CHANGE_IP_ADDRESS = 'CHANGE_IP_ADDRESS'; export const CHANGE_AXIOS_INTERCEPTOR = 'CHANGE_AXIOS_INTERCEPTOR'; export const CHANGE_LOAD_IMAGES = 'CHANGE_LOAD_IMAGES'; diff --git a/src/actions/userActions.js b/src/actions/userActions.js index eb1944a3d..db4497893 100644 --- a/src/actions/userActions.js +++ b/src/actions/userActions.js @@ -1,4 +1,4 @@ -import {CHANGE_AXIOS_INTERCEPTOR, CHANGE_IP_ADDRESS, CHANGE_USER_NAME_PASSWORD, SIGNOUT_REQUEST} from "./types"; +import {CHANGE_AUTH_KEY, CHANGE_AXIOS_INTERCEPTOR, CHANGE_IP_ADDRESS, SIGNOUT_REQUEST} from "./types"; /** * Sign out the current user and delete the redux cache @@ -18,8 +18,18 @@ export const signOut = () => dispatch => { */ export const changeUserNamePassword = (userName, password) => dispatch => { dispatch({ - type: CHANGE_USER_NAME_PASSWORD, - payload: {userName, password} + type: CHANGE_AUTH_KEY, + payload: {authKey: btoa(userName + ":" + password)} + }); + dispatch({ + type: CHANGE_AXIOS_INTERCEPTOR + }); +}; + +export const changeAuthKey = (authKey) => dispatch => { + dispatch({ + type: CHANGE_AUTH_KEY, + payload: {authKey: authKey} }); dispatch({ type: CHANGE_AXIOS_INTERCEPTOR diff --git a/src/containers/DefaultLayout/DefaultLayout.js b/src/containers/DefaultLayout/DefaultLayout.js index 171dc6a39..8f63183e5 100644 --- a/src/containers/DefaultLayout/DefaultLayout.js +++ b/src/containers/DefaultLayout/DefaultLayout.js @@ -19,7 +19,7 @@ import navigation from '../../_nav'; // routes config import routes from '../../routes'; import {connect} from "react-redux"; -import {PASSWORD_KEY, USER_NAME_KEY} from "../../utils/Constants"; +import {AUTH_KEY} from "../../utils/Constants"; import ErrorBoundary from "../../ErrorHandling/ErrorBoundary"; const DefaultAside = React.lazy(() => import('./DefaultAside')); @@ -32,7 +32,7 @@ class DefaultLayout extends Component { componentWillMount() { - if (!localStorage.getItem(USER_NAME_KEY) || !localStorage.getItem(PASSWORD_KEY)) { + if (!localStorage.getItem(AUTH_KEY)) { this.props.history.push('/login'); } } diff --git a/src/reducers/explorerStateReducer.js b/src/reducers/explorerStateReducer.js index 82eccc3f8..19a5de133 100644 --- a/src/reducers/explorerStateReducer.js +++ b/src/reducers/explorerStateReducer.js @@ -31,11 +31,9 @@ const initialState = { export default function (state = initialState, action) { const id = action.id; - // console.log(action.type); if (id) { let backStack = state.backStacks[id]; - // console.log(backStack, backStack instanceof BackStack); if (!backStack || !(backStack instanceof BackStack)) { @@ -76,7 +74,6 @@ export default function (state = initialState, action) { break; case CHANGE_REMOTE_NAME: - // console.log("CHange remote name", remoteName, remotePath) if (remoteName.indexOf('/') === 0) {/*The name starts with a /: local Name*/ remotePath = remoteName; remoteName = "/"; @@ -104,7 +101,6 @@ export default function (state = initialState, action) { case NAVIGATE_UP: // TODO: Write logic for up, which will navigate one directory up let current = backStack.peek(); - console.log(current); if (current.remotePath && current.remotePath !== "") { const splitPath = current.remotePath.split('/'); @@ -114,19 +110,14 @@ export default function (state = initialState, action) { current.remotePath = current.remotePath + ((i !== 0) ? '/' : '') + splitPath[i]; } } - console.log(current); backStack.push(current); break; case NAVIGATE_FWD: - // if(ptr < array.length){ - // ptr--; - // } backStack.moveForward(); break; case NAVIGATE_BACK: - // console.log(backStack); backStack.moveBack(); break; case CHANGE_VISIBILITY_FILTER: @@ -149,7 +140,6 @@ export default function (state = initialState, action) { default: break; } - // currentPath = backStack.peek(); return { ...state, backStacks: {...state.backStacks, [id]: backStack}, diff --git a/src/reducers/userActionsReducer.js b/src/reducers/userActionsReducer.js index aaa804b73..740d60a67 100644 --- a/src/reducers/userActionsReducer.js +++ b/src/reducers/userActionsReducer.js @@ -1,27 +1,29 @@ -import {CHANGE_AXIOS_INTERCEPTOR, CHANGE_IP_ADDRESS, CHANGE_USER_NAME_PASSWORD} from "../actions/types"; +import {CHANGE_AUTH_KEY, CHANGE_AXIOS_INTERCEPTOR, CHANGE_IP_ADDRESS} from "../actions/types"; import axiosInstance from "../utils/API/API"; -import {IP_ADDRESS_KEY, PASSWORD_KEY, USER_NAME_KEY} from "../utils/Constants"; +import {AUTH_KEY, IP_ADDRESS_KEY} from "../utils/Constants"; const initialState = { - auth: {userName: "", password: "", ipAddress: "http://localhost:5572", interceptor: ""} + auth: {authKey: "", ipAddress: "http://localhost:5572", interceptor: ""} }; /** * Specifies reducers for user actions like change username, password, ipAddress etc. * @param state * @param action - * @returns {{auth: {password: string, ipAddress: string, userName: string}}|({auth}&{auth: ((initialState.auth&*)|({password, ipAddress, userName}&*))})} + * @returns {{auth: {authKey: string, ipAddress: string}}|({auth}&{auth: ((initialState.auth&*)|({password, ipAddress, userName}&*))})} */ export default function (state = initialState, action) { switch (action.type) { - case CHANGE_USER_NAME_PASSWORD: + case CHANGE_AUTH_KEY: case CHANGE_IP_ADDRESS: state = { ...state, auth: {...state.auth, ...action.payload} }; - localStorage.setItem(USER_NAME_KEY, state.auth.userName); - localStorage.setItem(PASSWORD_KEY, state.auth.password); + console.log(state.auth.authKey); + localStorage.setItem(AUTH_KEY, state.auth.authKey); + // localStorage.setItem(USER_NAME_KEY, state.auth.userName); + // localStorage.setItem(PASSWORD_KEY, state.auth.password); localStorage.setItem(IP_ADDRESS_KEY, state.auth.ipAddress); return state; case CHANGE_AXIOS_INTERCEPTOR: @@ -31,7 +33,7 @@ export default function (state = initialState, action) { const interceptorID = axiosInstance.interceptors.request.use( config => { // Setup the configuration of authentication headers - config.headers.Authorization = 'Basic ' + btoa(localStorage.getItem(USER_NAME_KEY) + ":" + localStorage.getItem(PASSWORD_KEY)); + config.headers.Authorization = 'Basic ' + localStorage.getItem(AUTH_KEY); config.baseURL = localStorage.getItem("ipAddress"); return config; }, diff --git a/src/reducers/userActionsReducer.test.js b/src/reducers/userActionsReducer.test.js index 24d490154..cd25cba6f 100644 --- a/src/reducers/userActionsReducer.test.js +++ b/src/reducers/userActionsReducer.test.js @@ -1,10 +1,10 @@ import userActionsReducer from "./userActionsReducer"; -describe('Explorer Reducer', function () { +describe('User Actions Reducer', function () { it('should return default state', function () { const newState = userActionsReducer(undefined, {}); expect(newState).toEqual({ - auth: {userName: "", password: "", ipAddress: "http://localhost:5572", interceptor: ""} + auth: {authKey: "", ipAddress: "http://localhost:5572", interceptor: ""} }); }); diff --git a/src/utils/API/API.js b/src/utils/API/API.js index 4bb05d20c..448a2b65b 100644 --- a/src/utils/API/API.js +++ b/src/utils/API/API.js @@ -1,6 +1,6 @@ import axios from "axios"; import {isLocalRemoteName} from "../Tools"; -import {IP_ADDRESS_KEY, PASSWORD_KEY, USER_NAME_KEY} from "../Constants"; +import {AUTH_KEY, IP_ADDRESS_KEY} from "../Constants"; import urls from "./endpoint"; /** @@ -8,7 +8,8 @@ import urls from "./endpoint"; */ let axiosInstance = axios.create({ headers: {'Content-Type': 'application/json'}, - responseType: "json" + responseType: "json", + withCredentials: true }); /** @@ -17,7 +18,8 @@ let axiosInstance = axios.create({ axiosInstance.interceptors.request.use( config => { config.baseURL = localStorage.getItem(IP_ADDRESS_KEY); - config.headers.Authorization = 'Basic ' + btoa(localStorage.getItem(USER_NAME_KEY) + ":" + localStorage.getItem(PASSWORD_KEY)); + + config.headers.Authorization = 'Basic ' + localStorage.getItem(AUTH_KEY); return config; }, error => Promise.reject(error) diff --git a/src/utils/Constants.js b/src/utils/Constants.js index 55b79daf5..19d1fc837 100644 --- a/src/utils/Constants.js +++ b/src/utils/Constants.js @@ -19,6 +19,7 @@ export const NEW_DRIVE_CONFIG_REFRESH_TIMEOUT = 1000; export const MODAL_ROOT_ELEMENT = "modal-root"; export const USER_NAME_KEY = "userName"; +export const AUTH_KEY = "authKey"; export const PASSWORD_KEY = "password"; export const IP_ADDRESS_KEY = "ipAddress"; diff --git a/src/views/Explorer/RemotesList/RemotesList.js b/src/views/Explorer/RemotesList/RemotesList.js index ec04aa676..6a20558b1 100644 --- a/src/views/Explorer/RemotesList/RemotesList.js +++ b/src/views/Explorer/RemotesList/RemotesList.js @@ -41,7 +41,8 @@ class RemotesList extends React.Component { }; - openRemote = () => { + openRemote = (e) => { + e.preventDefault(); const {changeRemoteName, containerID} = this.props; const {remoteName} = this.state; changeRemoteName(containerID, remoteName); @@ -71,7 +72,7 @@ class RemotesList extends React.Component { } else { return ( -
this.openRemote()}> + @@ -80,8 +81,7 @@ class RemotesList extends React.Component { - + diff --git a/src/views/Pages/Login/Login.js b/src/views/Pages/Login/Login.js index 1b33505c7..fd1fb1b3a 100644 --- a/src/views/Pages/Login/Login.js +++ b/src/views/Pages/Login/Login.js @@ -15,18 +15,43 @@ import { UncontrolledAlert } from 'reactstrap'; import {connect} from "react-redux"; -import {changeIPAddress, changeUserNamePassword, signOut} from "../../../actions/userActions"; +import {changeAuthKey, changeIPAddress, changeUserNamePassword, signOut} from "../../../actions/userActions"; import axiosInstance from "../../../utils/API/API"; -import {IP_ADDRESS_KEY} from "../../../utils/Constants"; import urls from "../../../utils/API/endpoint"; + +function removeParam(parameter) { + let url = document.location.href; + let urlparts = url.split('?'); + + if (urlparts.length >= 2) { + let urlBase = urlparts.shift(); + let queryString = urlparts.join("?"); + + let prefix = encodeURIComponent(parameter) + '='; + let pars = queryString.split(/[&;]/g); + for (let i = pars.length; i-- > 0;) + if (pars[i].lastIndexOf(prefix, 0) !== -1) + pars.splice(i, 1); + if (pars.length > 0) + url = urlBase + '?' + pars.join('&'); + else + url = urlBase; + window.history.pushState('', document.title, url); // added this line to push the new url directly to url bar . + + } + return url; +} + class Login extends Component { constructor(props) { super(props); - let ipAddress = window.location.href.split("/#")[0]; - if (localStorage.getItem(IP_ADDRESS_KEY)) - ipAddress = localStorage.getItem(IP_ADDRESS_KEY); + let ipAddress = window.location.href.split("#/")[0]; + if (ipAddress.indexOf("?") !== -1) + ipAddress = window.location.href.split("?")[0]; + // if (localStorage.getItem(IP_ADDRESS_KEY)) + // ipAddress = localStorage.getItem(IP_ADDRESS_KEY); this.state = { username: "", password: "", @@ -57,19 +82,23 @@ class Login extends Component { }); }; + redirectToDashboard = () => { + this.props.history.push('/dashboard'); + }; + + onSubmit = e => { - e.preventDefault(); + if (e) + e.preventDefault(); + const {ipAddress, username, password} = this.state; Promise.all([ changeUserNamePassword(username, password), changeIPAddress(ipAddress) ]).then(() => { - this.props.history.push('/dashboard'); + this.redirectToDashboard() }); - // localStorage.setItem('username', username); - // localStorage.setItem('password', password); - // localStorage.setItem('ipAddress', ipAddress); }; @@ -105,6 +134,25 @@ class Login extends Component { componentDidMount() { localStorage.clear(); this.props.signOut(); + + + let url_string = window.location.href; + let url = new URL(url_string); + let loginToken = url.searchParams.get("login_token"); + let ipAddress = this.state.ipAddress; + if (url.searchParams.get("ip_address")) { + ipAddress = url.searchParams.get("ip_address"); + } + // console.log(loginToken); + if (loginToken) { + Promise.all([ + this.props.changeAuthKey(loginToken), + this.props.changeIPAddress(ipAddress) + ]); + removeParam("login_token"); + removeParam("ip_address"); + this.redirectToDashboard(); + } } @@ -183,4 +231,4 @@ class Login extends Component { } -export default connect(null, {signOut, changeUserNamePassword, changeIPAddress})(Login); +export default connect(null, {signOut, changeUserNamePassword, changeIPAddress, changeAuthKey})(Login); diff --git a/src/views/Pages/Login/Login.test.js b/src/views/Pages/Login/Login.test.js index d92431da5..dca6816b4 100644 --- a/src/views/Pages/Login/Login.test.js +++ b/src/views/Pages/Login/Login.test.js @@ -14,7 +14,7 @@ const setUp = (intialState = {}, props = {}) => { }; -describe('Remote Explorer Layout', function () { +describe('Login Layout', function () { describe('renders', function () { diff --git a/src/views/Pages/Login/__snapshots__/Login.test.js.snap b/src/views/Pages/Login/__snapshots__/Login.test.js.snap index f19d20b8a..d780bf225 100644 --- a/src/views/Pages/Login/__snapshots__/Login.test.js.snap +++ b/src/views/Pages/Login/__snapshots__/Login.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Remote Explorer Layout renders should match snapshot 1`] = ` +exports[`Login Layout renders should match snapshot 1`] = `