Skip to content

Commit

Permalink
Login: Auto login when run through the rclone cli.
Browse files Browse the repository at this point in the history
Login: Auto login when run through the rclone cli.

Login: Auto login when run through the rclone cli.
  • Loading branch information
negative0 committed Aug 16, 2019
1 parent 2e2f0d2 commit a95c0fb
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 46 deletions.
3 changes: 2 additions & 1 deletion src/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
16 changes: 13 additions & 3 deletions src/actions/userActions.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/containers/DefaultLayout/DefaultLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand All @@ -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');
}
}
Expand Down
10 changes: 0 additions & 10 deletions src/reducers/explorerStateReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {


Expand Down Expand Up @@ -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 = "/";
Expand Down Expand Up @@ -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('/');
Expand All @@ -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:
Expand All @@ -149,7 +140,6 @@ export default function (state = initialState, action) {
default:
break;
}
// currentPath = backStack.peek();
return {
...state,
backStacks: {...state.backStacks, [id]: backStack},
Expand Down
18 changes: 10 additions & 8 deletions src/reducers/userActionsReducer.js
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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;
},
Expand Down
4 changes: 2 additions & 2 deletions src/reducers/userActionsReducer.test.js
Original file line number Diff line number Diff line change
@@ -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: ""}
});
});

Expand Down
8 changes: 5 additions & 3 deletions src/utils/API/API.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
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";

/**
* Global level axios configuration. These settings are automatically used in other places by using an axiosInstance instead of axios directly
*/
let axiosInstance = axios.create({
headers: {'Content-Type': 'application/json'},
responseType: "json"
responseType: "json",
withCredentials: true
});

/**
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/utils/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
8 changes: 4 additions & 4 deletions src/views/Explorer/RemotesList/RemotesList.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -71,7 +72,7 @@ class RemotesList extends React.Component {
} else {

return (
<Form onSubmit={() => this.openRemote()}>
<Form onSubmit={this.openRemote}>
<Row>

<Col xs={12} sm={10} lg={8}>
Expand All @@ -80,8 +81,7 @@ class RemotesList extends React.Component {
</Col>
<Col xs={12} sm={2} lg={4}>

<Button className={"btn-lg"} color="success"
type="submit">{this.state.openButtonText}</Button>
<Button className={"btn-lg"} color="success">{this.state.openButtonText}</Button>
</Col>

</Row>
Expand Down
70 changes: 59 additions & 11 deletions src/views/Pages/Login/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: "",
Expand Down Expand Up @@ -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);

};

Expand Down Expand Up @@ -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();
}
}


Expand Down Expand Up @@ -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);
2 changes: 1 addition & 1 deletion src/views/Pages/Login/Login.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const setUp = (intialState = {}, props = {}) => {
};


describe('Remote Explorer Layout', function () {
describe('Login Layout', function () {


describe('renders', function () {
Expand Down
2 changes: 1 addition & 1 deletion src/views/Pages/Login/__snapshots__/Login.test.js.snap
Original file line number Diff line number Diff line change
@@ -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`] = `
<div
className="app flex-row align-items-center"
data-test="loginComponent"
Expand Down

0 comments on commit a95c0fb

Please sign in to comment.