Selaa lähdekoodia

fix: fix all eslint warnings

drac 5 vuotta sitten
vanhempi
commit
0cd02a1f8b

+ 2 - 1
webui/ovpm/.eslintrc.json

@@ -14,7 +14,8 @@
     "react/jsx-one-expression-per-line": "off",
     "react-hooks/rules-of-hooks": "off",
     "react-hooks/exhaustive-deps": "off",
-    "no-undef": "off"
+    "no-undef": "off",
+    "jsx-a11y/anchor-is-valid": "off"
   }
 }
 

+ 62 - 60
webui/ovpm/src/api.js

@@ -1,65 +1,67 @@
-export var baseURL = window.location.protocol + "//" + window.location.host + "/api/v1"
+export var baseURL =
+  window.location.protocol + "//" + window.location.host + "/api/v1";
 
-if (process.env.NODE_ENV !== 'production') {
-		baseURL = "http://" + window.location.hostname + ":8383/api/v1" // local pc external ip
+if (process.env.NODE_ENV !== "production") {
+  // baseURL = "http://172.16.16.53:8080/api/v1" // local pc external ip
+  baseURL = "http://dfd978a2.ngrok.io/api/v1";
 }
 
 export const endpoints = {
-    authenticate: {
-        path: "/auth/authenticate",
+  authenticate: {
+    path: "/auth/authenticate",
 
-        method: "POST",
-    },
-    authStatus: {
-        path: "/auth/status",
-        method: "GET",
-    },
-    genConfig: {
-        path: "/user/genconfig",
-        method: "POST",
-    },
-    userList: {
-        path: "/user/list",
-        method: "GET",
-    },
-    userCreate: {
-        path: "/user/create",
-        method: "POST",
-    },
-    userDelete: {
-        path: "/user/delete",
-        method: "POST",
-    },
-    userUpdate: {
-        path: "/user/update",
-        method: "POST",
-    },
-    networkList: {
-        path: "/network/list",
-        method: "GET",
-    },
-    vpnStatus: {
-        path: "/vpn/status",
-        method: "GET",
-    },
-    vpnRestart: {
-        path: "/vpn/restart",
-        method: "POST",
-    },
-    netDefine: {
-        path: "/network/create",
-        method: "POST",
-    },
-    netUndefine: {
-        path: "/network/delete",
-        method: "POST",
-    },
-    netAssociate: {
-        path: "/network/associate",
-        method: "POST",
-    },
-    netDissociate: {
-        path: "/network/dissociate",
-        method: "POST",
-    }
-}
+    method: "POST"
+  },
+  authStatus: {
+    path: "/auth/status",
+    method: "GET"
+  },
+  genConfig: {
+    path: "/user/genconfig",
+    method: "POST"
+  },
+  userList: {
+    path: "/user/list",
+    method: "GET"
+  },
+  userCreate: {
+    path: "/user/create",
+    method: "POST"
+  },
+  userDelete: {
+    path: "/user/delete",
+    method: "POST"
+  },
+  userUpdate: {
+    path: "/user/update",
+    method: "POST"
+  },
+  networkList: {
+    path: "/network/list",
+    method: "GET"
+  },
+  vpnStatus: {
+    path: "/vpn/status",
+    method: "GET"
+  },
+  vpnRestart: {
+    path: "/vpn/restart",
+    method: "POST"
+  },
+  netDefine: {
+    path: "/network/create",
+    method: "POST"
+  },
+  netUndefine: {
+    path: "/network/delete",
+    method: "POST"
+  },
+  netAssociate: {
+    path: "/network/associate",
+    method: "POST"
+  },
+  netDissociate: {
+    path: "/network/dissociate",
+    method: "POST"
+  }
+};

+ 158 - 105
webui/ovpm/src/components/Auth/Login/index.jsx

@@ -1,127 +1,180 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import Button from 'muicss/lib/react/button';
-import Input from 'muicss/lib/react/input';
-import Panel from 'muicss/lib/react/panel';
-import Container from 'muicss/lib/react/container';
+import React from "react";
+import Button from "muicss/lib/react/button";
+import Input from "muicss/lib/react/input";
+import Panel from "muicss/lib/react/panel";
+import Container from "muicss/lib/react/container";
 
-import { Redirect } from 'react-router'
+import { Redirect } from "react-router";
 
-import {IsAuthenticated, SetAuthToken, ClearAuthToken, SetItem, GetItem} from '../../../utils/auth.js';
-import {API} from '../../../utils/restClient.js';
-import {baseURL, endpoints} from '../../../api.js';
+import {
+  IsAuthenticated,
+  SetAuthToken,
+  ClearAuthToken,
+  SetItem,
+  GetItem
+} from "../../../utils/auth.js";
+import { API } from "../../../utils/restClient.js";
+import { baseURL, endpoints } from "../../../api.js";
 
 export default class Login extends React.Component {
-    constructor(props) {
-        super(props)
+  constructor(props) {
+    super(props);
 
-        this.state = {
-            username: "",
-            password: "",
-            isAuthenticated: false,
-            isAdmin: false,
-            error: null,
-        }
-        this.api = new API(baseURL, endpoints)
-    }
+    this.state = {
+      username: "",
+      password: "",
+      isAuthenticated: false,
+      isAdmin: false,
+      error: null
+    };
+    this.api = new API(baseURL, endpoints);
+  }
 
-    componentWillMount() {
-        let isAdmin = false
-        if (GetItem("isAdmin")) {
-            isAdmin = true
-        }
-        this.setState({
-            isAuthenticated: IsAuthenticated(),
-            isAdmin: isAdmin,
-        })
-        this.api.call("authStatus", {}, false, this.handleGetUserInfoSuccess.bind(this), this.handleGetUserInfoFailure.bind(this))
+  componentWillMount() {
+    let isAdmin = false;
+    if (GetItem("isAdmin")) {
+      isAdmin = true;
     }
+    this.setState({
+      isAuthenticated: IsAuthenticated(),
+      isAdmin: isAdmin
+    });
+    this.api.call(
+      "authStatus",
+      {},
+      false,
+      this.handleGetUserInfoSuccess.bind(this),
+      this.handleGetUserInfoFailure.bind(this)
+    );
+  }
 
-    handleUsernameChange(e) {
-        this.setState({username: e.target.value})
-    }
+  handleUsernameChange(e) {
+    this.setState({ username: e.target.value });
+  }
 
-    handlePasswordChange(e) {
-        this.setState({password: e.target.value})
-    }
+  handlePasswordChange(e) {
+    this.setState({ password: e.target.value });
+  }
 
-    handleGetUserInfoSuccess(res) {
-        if (res.data.user.username === "root") {
-            SetAuthToken("root")
-            this.setState({isAuthenticated: true})
-            this.api.setAuthToken("root")
-            SetItem("isAdmin", true)
-            SetItem("username", "root")
-        } else {
-            SetItem("isAdmin", res.data.user.is_admin)
-            SetItem("username", this.state.username)
-        }
+  handleGetUserInfoSuccess(res) {
+    if (res.data.user.username === "root") {
+      SetAuthToken("root");
+      this.setState({ isAuthenticated: true });
+      this.api.setAuthToken("root");
+      SetItem("isAdmin", true);
+      SetItem("username", "root");
+    } else {
+      SetItem("isAdmin", res.data.user.is_admin);
+      SetItem("username", this.state.username);
     }
+  }
 
-    handleGetUserInfoFailure(error) {
-        console.log(error)
-    }
+  handleGetUserInfoFailure(error) {
+    console.log(error);
+  }
 
-    handleAuthenticateSuccess(res) {
-        SetAuthToken(res.data.token)
-        this.setState({isAuthenticated: true})
-        console.log("authenticated")
-        this.api.setAuthToken(res.data.token)
-        this.api.call("authStatus", {}, true, this.handleGetUserInfoSuccess.bind(this), this.handleGetUserInfoFailure.bind(this))
-    }
+  handleAuthenticateSuccess(res) {
+    SetAuthToken(res.data.token);
+    this.setState({ isAuthenticated: true });
+    console.log("authenticated");
+    this.api.setAuthToken(res.data.token);
+    this.api.call(
+      "authStatus",
+      {},
+      true,
+      this.handleGetUserInfoSuccess.bind(this),
+      this.handleGetUserInfoFailure.bind(this)
+    );
+  }
 
-    handleAuthenticateFailure(error) {
-        ClearAuthToken()
-        this.setState({isAuthenticated: false})
-        console.log("authentication error", error)
-        if (error.response.status >= 400) {
-            this.setState({error: "Your credentials are incorrect."})
-        }
+  handleAuthenticateFailure(error) {
+    ClearAuthToken();
+    this.setState({ isAuthenticated: false });
+    console.log("authentication error", error);
+    if (error.response.status >= 400) {
+      this.setState({ error: "Your credentials are incorrect." });
     }
+  }
 
-    handleFormSubmit(e) {
-        this.setState({error: null})
-        if (!this.state.username) {
-            return
-        }
-        if (!this.state.password) {
-            return
-        }
+  handleFormSubmit(e) {
+    this.setState({ error: null });
+    if (!this.state.username) {
+      return;
+    }
+    if (!this.state.password) {
+      return;
+    }
 
-        let data = {
-            username: this.state.username,
-            password: this.state.password
-        }
+    let data = {
+      username: this.state.username,
+      password: this.state.password
+    };
 
-        this.api.call("authenticate", data, false, this.handleAuthenticateSuccess.bind(this), this.handleAuthenticateFailure.bind(this))
-        e.preventDefault()
+    this.api.call(
+      "authenticate",
+      data,
+      false,
+      this.handleAuthenticateSuccess.bind(this),
+      this.handleAuthenticateFailure.bind(this)
+    );
+    e.preventDefault();
+  }
+  render() {
+    let error;
+    if (this.state.isAuthenticated) {
+      return <Redirect to="/dashboard" />;
     }
-    render() {
-        let error
-        if (this.state.isAuthenticated) {
-            return <Redirect to="/dashboard" />
-        }
 
-        if (this.state.error) {
-            error = (
-                <Panel className="mui--text-center" style={{"color": "#fff", "background-color": "#F44336", "margin-bottom":"0", "padding-bottom": "0"}}>
-                    <b>Authentication Error</b>
-                    <p>{this.state.error}</p>
-                </Panel>)
-        }
-        return (
-            <div style={{"maxWidth": "500px", "marginTop": "calc(50vh - 232px / 2)", "marginLeft": "calc(50% - 500px / 2)"}}>
-                <Container>
-                    {error}
-                    <Panel>
-                        <form onSubmit={this.handleFormSubmit.bind(this)}>
-                            <Input label="Username" value={this.state.username} onChange={this.handleUsernameChange.bind(this)} floatingLabel={true} required={true} />
-                            <Input label="Password" value={this.state.password} onChange={this.handlePasswordChange.bind(this)} floatingLabel={true} required={true} type="password" />
-                            <Button type="submit" color="primary" required={true}>Login</Button>
-                        </form>
-                    </Panel>
-                </Container>
-            </div>
-        )
+    if (this.state.error) {
+      error = (
+        <Panel
+          className="mui--text-center"
+          style={{
+            color: "#fff",
+            "background-color": "#F44336",
+            "margin-bottom": "0",
+            "padding-bottom": "0"
+          }}
+        >
+          <b>Authentication Error</b>
+          <p>{this.state.error}</p>
+        </Panel>
+      );
     }
+    return (
+      <div
+        style={{
+          maxWidth: "500px",
+          marginTop: "calc(50vh - 232px / 2)",
+          marginLeft: "calc(50% - 500px / 2)"
+        }}
+      >
+        <Container>
+          {error}
+          <Panel>
+            <form onSubmit={this.handleFormSubmit.bind(this)}>
+              <Input
+                label="Username"
+                value={this.state.username}
+                onChange={this.handleUsernameChange.bind(this)}
+                floatingLabel={true}
+                required={true}
+              />
+              <Input
+                label="Password"
+                value={this.state.password}
+                onChange={this.handlePasswordChange.bind(this)}
+                floatingLabel={true}
+                required={true}
+                type="password"
+              />
+              <Button type="submit" color="primary" required={true}>
+                Login
+              </Button>
+            </form>
+          </Panel>
+        </Container>
+      </div>
+    );
+  }
 }

+ 18 - 20
webui/ovpm/src/components/Auth/LoginRequired/index.jsx

@@ -1,26 +1,24 @@
-import React from 'react';
+import React from "react";
 
-import { Redirect } from 'react-router'
+import { Redirect } from "react-router";
 
-import {IsAuthenticated} from '../../../utils/auth.js';
+import { IsAuthenticated } from "../../../utils/auth.js";
 
 export default function loginRequired(WrappedComponent) {
-    return class extends React.Component {
-        componentWillReceiveProps(nextProps) {
-            console.log('Current props: ', this.props);
-            console.log('Next props: ', nextProps);
-            this.state = {
-                isLoggedIn: false
-            }
-        }
-        componentWillMount () {
-            this.setState({isLoggedIn: IsAuthenticated()})
-        }
-        render() {
-            if (!this.state.isLoggedIn) {
-                return <Redirect to="/login" />
-            }
-            return <WrappedComponent {...this.props} />;
-        }
+  return class extends React.Component {
+    componentWillReceiveProps(nextProps) {
+      console.log("Current props: ", this.props);
+      console.log("Next props: ", nextProps);
+      this.setState({ isLoggedIn: false });
     }
+    componentWillMount() {
+      this.setState({ isLoggedIn: IsAuthenticated() });
+    }
+    render() {
+      if (!this.state.isLoggedIn) {
+        return <Redirect to="/login" />;
+      }
+      return <WrappedComponent {...this.props} />;
+    }
+  };
 }

+ 9 - 13
webui/ovpm/src/components/Auth/Logout/index.jsx

@@ -1,16 +1,12 @@
-import React from 'react';
-import { Redirect } from 'react-router'
-import {ClearAuthToken} from '../../../utils/auth.js';
+import React from "react";
+import { Redirect } from "react-router";
+import { ClearAuthToken } from "../../../utils/auth.js";
 export default class Logout extends React.Component {
-    constructor(props) {
-        super(props)
-    }
+  componentWillMount() {
+    ClearAuthToken(); // Logout
+  }
 
-    componentWillMount () {
-        ClearAuthToken() // Logout
-    }
-
-    render() {
-        return <Redirect to="/login" />
-    }
+  render() {
+    return <Redirect to="/login" />;
+  }
 }

+ 113 - 78
webui/ovpm/src/components/Dashboard/AdminDashboard/NetworkEdit/index.jsx

@@ -1,84 +1,119 @@
-import React from 'react';
-
-import Button from 'muicss/lib/react/button';
-import Container from 'muicss/lib/react/container';
-import Input from 'muicss/lib/react/input';
-import Option from 'muicss/lib/react/option';
-import Select from 'muicss/lib/react/select';
-import Checkbox from 'muicss/lib/react/checkbox';
+import React from "react";
 
+import Button from "muicss/lib/react/button";
+import Container from "muicss/lib/react/container";
+import Input from "muicss/lib/react/input";
+import Option from "muicss/lib/react/option";
+import Select from "muicss/lib/react/select";
 
 export default class NetworkEdit extends React.Component {
-    constructor(props) {
-        super(props)
-
-        this.state = {
-            name: this.props.name ? this.props.name : "",
-            type: this.props.type ? this.props.type : "SERVERNET",
-            cidr: this.props.cidr ? this.props.cidr : "",
-            via: this.props.via ? this.props.via : "",
-        }
-    }
-
-    componentWillMount() {
-    }
-
-    handleNameChange(e) {
-        this.setState({name: e.target.value})
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      name: this.props.name ? this.props.name : "",
+      type: this.props.type ? this.props.type : "SERVERNET",
+      cidr: this.props.cidr ? this.props.cidr : "",
+      via: this.props.via ? this.props.via : ""
+    };
+  }
+
+  componentWillMount() {}
+
+  handleNameChange(e) {
+    this.setState({ name: e.target.value });
+  }
+
+  handleTypeChange(e) {
+    this.setState({ type: e.target.value });
+  }
+
+  handleCidrChange(e) {
+    this.setState({ cidr: e.target.value });
+  }
+
+  handleViaChange(e) {
+    this.setState({ via: e.target.value });
+  }
+
+  handleFormSubmit() {
+    console.log(this.state.type);
+    let network = {
+      name: this.state.name,
+      cidr: this.state.cidr,
+      type: this.state.type,
+      via: this.state.via
+    };
+
+    this.props.onSave(network);
+  }
+
+  handleFormCancel() {
+    this.setState({ error: null });
+    this.props.onCancel();
+  }
+
+  render() {
+    var via;
+    if (this.state.type === "ROUTE") {
+      via = (
+        <Input
+          label="Via (Optional)"
+          value={this.state.via}
+          onChange={this.handleViaChange.bind(this)}
+          floatingLabel={true}
+          required={false}
+        />
+      );
     }
 
-    handleTypeChange(e) {
-        this.setState({type: e.target.value})
-    }
-
-    handleCidrChange(e) {
-        this.setState({cidr: e.target.value})
-    }
-
-    handleViaChange(e) {
-        this.setState({via: e.target.value})
-    }
-
-    handleFormSubmit() {
-        console.log(this.state.type)
-        let network = {
-            name: this.state.name,
-            cidr: this.state.cidr,
-            type: this.state.type,
-            via: this.state.via,
-        }
-
-        this.props.onSave(network)
-    }
-
-    handleFormCancel() {
-        this.setState({error: null})
-        this.props.onCancel()
-    }
-
-    render() {
-        var via
-        if (this.state.type === "ROUTE") {
-            via = <Input label="Via (Optional)" value={this.state.via} onChange={this.handleViaChange.bind(this)} floatingLabel={true} required={false} />
-        }
-
-        return (
-            <Container>
-                <h1>{this.props.title}</h1>
-
-                <Input label="Name" value={this.state.name} onChange={this.handleNameChange.bind(this)} floatingLabel={true} required={true} disabled={this.props.isNameDisabled}/>
-                <Input label="CIDR" value={this.state.cidr} onChange={this.handleCidrChange.bind(this)} floatingLabel={true} required={true} />
-                <Select name="type" label="Type" value={this.state.type} onChange={this.handleTypeChange.bind(this)}>
-                    <Option value="SERVERNET" label="SERVERNET" />
-                    <Option value="ROUTE" label="ROUTE" />
-                </Select>
-                {via}
-
-                <div className="mui--pull-right">
-                    <Button color="primary" onClick={this.handleFormSubmit.bind(this)} required={true}>Save</Button>
-                    <Button color="danger" onClick={this.handleFormCancel.bind(this)} required={true}>Cancel</Button>
-                </div>
-            </Container>
-        )
-    }
+    return (
+      <Container>
+        <h1>{this.props.title}</h1>
+
+        <Input
+          label="Name"
+          value={this.state.name}
+          onChange={this.handleNameChange.bind(this)}
+          floatingLabel={true}
+          required={true}
+          disabled={this.props.isNameDisabled}
+        />
+        <Input
+          label="CIDR"
+          value={this.state.cidr}
+          onChange={this.handleCidrChange.bind(this)}
+          floatingLabel={true}
+          required={true}
+        />
+        <Select
+          name="type"
+          label="Type"
+          value={this.state.type}
+          onChange={this.handleTypeChange.bind(this)}
+        >
+          <Option value="SERVERNET" label="SERVERNET" />
+          <Option value="ROUTE" label="ROUTE" />
+        </Select>
+        {via}
+
+        <div className="mui--pull-right">
+          <Button
+            color="primary"
+            onClick={this.handleFormSubmit.bind(this)}
+            required={true}
+          >
+            Save
+          </Button>
+          <Button
+            color="danger"
+            onClick={this.handleFormCancel.bind(this)}
+            required={true}
+          >
+            Cancel
+          </Button>
+        </div>
+      </Container>
+    );
+  }
 }

+ 128 - 90
webui/ovpm/src/components/Dashboard/AdminDashboard/UserEdit/index.jsx

@@ -1,95 +1,133 @@
-import React from 'react';
-
-import Button from 'muicss/lib/react/button';
-import Container from 'muicss/lib/react/container';
-import Input from 'muicss/lib/react/input';
-import Option from 'muicss/lib/react/option';
-import Select from 'muicss/lib/react/select';
-import Checkbox from 'muicss/lib/react/checkbox';
-import Textarea from 'muicss/lib/react/textarea';
-
+import React from "react";
 
+import Button from "muicss/lib/react/button";
+import Container from "muicss/lib/react/container";
+import Input from "muicss/lib/react/input";
+import Option from "muicss/lib/react/option";
+import Select from "muicss/lib/react/select";
+import Checkbox from "muicss/lib/react/checkbox";
 
 export default class UserEdit extends React.Component {
-    constructor(props) {
-        super(props)
-
-        this.state = {
-            username: this.props.username ? this.props.username : "",
-            password: "",
-            staticIP: this.props.staticIP ? this.props.staticIP : "",
-            ipAllocationMethod: this.props.ipAllocationMethod ? this.props.ipAllocationMethod : "dynamic",
-            pushGW: this.props.pushGW != undefined ? this.props.pushGW : true,
-            isAdmin: this.props.isAdmin ? this.props.isAdmin : false,
-            description: this.props.description ? this.props.description : "",
-        }
-
-    }
-
-    componentWillMount() {
-    }
-
-    handleUsernameChange(e) {
-        this.setState({username: e.target.value})
-    }
-
-    handlePasswordChange(e) {
-        this.setState({password: e.target.value})
-    }
-    handleDescriptionChange(e) {
-        this.setState({description: e.target.value})
-    }
-
-    handleStaticIPChange(e) {
-        this.setState({staticIP: e.target.value})
-    }
-
-    handleIPAllocationChange(e) {
-        this.setState({ipAllocationMethod: e.target.value})
-    }
-
-    handlePushGWChange (e) {
-        this.setState({pushGW: e.target.checked})
-    }
-
-    handleIsAdminChange (e) {
-        this.setState({isAdmin: e.target.checked})
-    }
-
-    handleFormSubmit() {
-        this.props.onSave(this.state)
-    }
-
-    handleFormCancel() {
-        this.setState({error: null})
-        this.props.onCancel()
-    }
-
-    render() {
-        var staticIPInput
-        if (this.state.ipAllocationMethod === "static") {
-            staticIPInput = <Input label="Address" value={this.state.staticIP} onChange={this.handleStaticIPChange.bind(this)} floatingLabel={true} required={true} />
-        }
-        return (
-            <Container>
-                <h1>{this.props.title}</h1>
-
-                <Input label="Username" value={this.state.username} onChange={this.handleUsernameChange.bind(this)} floatingLabel={true} required={true} disabled={this.props.isUsernameDisabled}/>
-                <Input label="Password" value={this.state.password} onChange={this.handlePasswordChange.bind(this)} floatingLabel={true} required={true} type="password"/>
-                <Select name="ip" label="IP Allocation" value={this.state.ipAllocationMethod} onChange={this.handleIPAllocationChange.bind(this)}>
-                    <Option value="dynamic" label="Dynamic" />
-                    <Option value="static" label="Static" />
-                </Select>
-                {staticIPInput}
-                <Checkbox label="Push GW" checked={this.state.pushGW} onChange={this.handlePushGWChange.bind(this)}/>
-                <Checkbox label="Make Admin" checked={this.state.isAdmin} onChange={this.handleIsAdminChange.bind(this)}/>
-                <Textarea placeholder="User description" value={this.state.description} onChange={this.handleDescriptionChange.bind(this)} cols={50} rows={5} />
-
-                    <div className="mui--pull-right">
-                    <Button color="primary" onClick={this.handleFormSubmit.bind(this)} required={true}>Save</Button>
-                    <Button color="danger" onClick={this.handleFormCancel.bind(this)} required={true}>Cancel</Button>
-                </div>
-            </Container>
-        )
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      username: this.props.username ? this.props.username : "",
+      password: "",
+      staticIP: this.props.staticIP ? this.props.staticIP : "",
+      ipAllocationMethod: this.props.ipAllocationMethod
+        ? this.props.ipAllocationMethod
+        : "dynamic",
+      pushGW: this.props.pushGW !== undefined ? this.props.pushGW : true,
+      isAdmin: this.props.isAdmin ? this.props.isAdmin : false
+    };
+  }
+
+  componentWillMount() {}
+
+  handleUsernameChange(e) {
+    this.setState({ username: e.target.value });
+  }
+
+  handlePasswordChange(e) {
+    this.setState({ password: e.target.value });
+  }
+
+  handleStaticIPChange(e) {
+    this.setState({ staticIP: e.target.value });
+  }
+
+  handleIPAllocationChange(e) {
+    this.setState({ ipAllocationMethod: e.target.value });
+  }
+
+  handlePushGWChange(e) {
+    this.setState({ pushGW: e.target.checked });
+  }
+
+  handleIsAdminChange(e) {
+    this.setState({ isAdmin: e.target.checked });
+  }
+
+  handleFormSubmit() {
+    this.props.onSave(this.state);
+  }
+
+  handleFormCancel() {
+    this.setState({ error: null });
+    this.props.onCancel();
+  }
+
+  render() {
+    var staticIPInput;
+    if (this.state.ipAllocationMethod === "static") {
+      staticIPInput = (
+        <Input
+          label="Address"
+          value={this.state.staticIP}
+          onChange={this.handleStaticIPChange.bind(this)}
+          floatingLabel={true}
+          required={true}
+        />
+      );
     }
+    return (
+      <Container>
+        <h1>{this.props.title}</h1>
+
+        <Input
+          label="Username"
+          value={this.state.username}
+          onChange={this.handleUsernameChange.bind(this)}
+          floatingLabel={true}
+          required={true}
+          disabled={this.props.isUsernameDisabled}
+        />
+        <Input
+          label="Password"
+          value={this.state.password}
+          onChange={this.handlePasswordChange.bind(this)}
+          floatingLabel={true}
+          required={true}
+          type="password"
+        />
+        <Select
+          name="ip"
+          label="IP Allocation"
+          value={this.state.ipAllocationMethod}
+          onChange={this.handleIPAllocationChange.bind(this)}
+        >
+          <Option value="dynamic" label="Dynamic" />
+          <Option value="static" label="Static" />
+        </Select>
+        {staticIPInput}
+        <Checkbox
+          label="Push GW"
+          checked={this.state.pushGW}
+          onChange={this.handlePushGWChange.bind(this)}
+        />
+        <Checkbox
+          label="Make Admin"
+          checked={this.state.isAdmin}
+          onChange={this.handleIsAdminChange.bind(this)}
+        />
+        <div className="mui--pull-right">
+          <Button
+            color="primary"
+            onClick={this.handleFormSubmit.bind(this)}
+            required={true}
+          >
+            Save
+          </Button>
+          <Button
+            color="danger"
+            onClick={this.handleFormCancel.bind(this)}
+            required={true}
+          >
+            Cancel
+          </Button>
+        </div>
+      </Container>
+    );
+  }
 }

+ 63 - 48
webui/ovpm/src/components/Dashboard/AdminDashboard/UserPicker/index.jsx

@@ -1,60 +1,75 @@
-import React from 'react';
-
-import Button from 'muicss/lib/react/button';
-import Container from 'muicss/lib/react/container';
-import Input from 'muicss/lib/react/input';
-import Option from 'muicss/lib/react/option';
-import Select from 'muicss/lib/react/select';
-import Checkbox from 'muicss/lib/react/checkbox';
+import React from "react";
 
+import Button from "muicss/lib/react/button";
+import Container from "muicss/lib/react/container";
+import Option from "muicss/lib/react/option";
+import Select from "muicss/lib/react/select";
 
 export default class UserPicker extends React.Component {
-    constructor(props) {
-        super(props)
+  constructor(props) {
+    super(props);
 
-        this.state = {
-            username: this.props.userNames.length > 0 ? this.props.userNames[0] : "",
-        }
+    this.state = {
+      username: this.props.userNames.length > 0 ? this.props.userNames[0] : ""
+    };
+  }
 
-    }
+  componentWillMount() {}
 
-    componentWillMount() {
-    }
+  handleUserChange(e) {
+    this.setState({ username: e.target.value });
+  }
 
+  handleFormSubmit() {
+    this.props.onSave(this.state.username);
+    console.log(this.state.username);
+  }
 
-    handleUserChange(e) {
-        this.setState({username: e.target.value})
-    }
+  handleFormCancel() {
+    this.setState({ error: null });
+    this.props.onCancel();
+  }
 
-    handleFormSubmit() {
-        this.props.onSave(this.state.username)
-        console.log(this.state.username)
+  render() {
+    let users = [];
+    for (let i in this.props.userNames) {
+      users.push(
+        <Option
+          key={i}
+          value={this.props.userNames[i]}
+          label={this.props.userNames[i]}
+        />
+      );
     }
+    return (
+      <Container>
+        <h1>{this.props.title}</h1>
 
-    handleFormCancel() {
-        this.setState({error: null})
-        this.props.onCancel()
-    }
-
-    render() {
-        let users = []
-        for(let i in this.props.userNames) {
-            users.push(
-                <Option key={i} value={this.props.userNames[i]} label={this.props.userNames[i]} />
-            )
-        }
-        return (
-            <Container>
-                <h1>{this.props.title}</h1>
-
-                <Select name="user" label="User" value={this.state.username} onChange={this.handleUserChange.bind(this)}>
-                    {users}
-                </Select>
-                <div className="mui--pull-right">
-                    <Button color="primary" onClick={this.handleFormSubmit.bind(this)} required={true}>Save</Button>
-                    <Button color="danger" onClick={this.handleFormCancel.bind(this)} required={true}>Cancel</Button>
-                </div>
-            </Container>
-        )
-    }
+        <Select
+          name="user"
+          label="User"
+          value={this.state.username}
+          onChange={this.handleUserChange.bind(this)}
+        >
+          {users}
+        </Select>
+        <div className="mui--pull-right">
+          <Button
+            color="primary"
+            onClick={this.handleFormSubmit.bind(this)}
+            required={true}
+          >
+            Save
+          </Button>
+          <Button
+            color="danger"
+            onClick={this.handleFormCancel.bind(this)}
+            required={true}
+          >
+            Cancel
+          </Button>
+        </div>
+      </Container>
+    );
+  }
 }

+ 22 - 22
webui/ovpm/src/components/Dashboard/AdminDashboard/index.jsx

@@ -28,7 +28,7 @@ const modalStyle = {
 const CREATINGNEWUSER = "CREATINGNEWUSER";
 const EDITINGUSER = "EDITINGUSER";
 const DEFININGNEWNETWORK = "DEFININGNEWNETWORK";
-const EDITINGNETWORK = "EDITINGNETWORK";
+// const EDITINGNETWORK = "EDITINGNETWORK";
 const ASSOCIATINGUSER = "ASSOCIATINGUSER";
 const DISSOCIATINGUSER = "DISSOCIATINGUSER";
 
@@ -54,7 +54,7 @@ function dot2num(dot) {
 
 function num2dot(num) {
   var d = num % 256;
-  for (var i = 3; i > 0; i--) {
+  for (let i = 3; i > 0; i--) {
     num = Math.floor(num / 256);
     d = (num % 256) + "." + d;
   }
@@ -143,7 +143,7 @@ export default class AdminDashboard extends React.Component {
   }
 
   handleGetUsersFailure(error) {
-    if ("response" in error && error.response.status == 401) {
+    if ("response" in error && error.response.status === 401) {
       this.handleAuthFailure(error);
     }
     this.setState({ users: [] });
@@ -156,7 +156,7 @@ export default class AdminDashboard extends React.Component {
   handleGetNetworksFailure(error) {
     console.log(error);
     this.setState({ networks: [] });
-    if (error.response.status == 401) {
+    if (error.response.status === 401) {
       this.handleAuthFailure(error);
     }
   }
@@ -168,7 +168,7 @@ export default class AdminDashboard extends React.Component {
   handleGetVPNStatusFailure(error) {
     console.log(error);
     this.setState({ vpn: {} });
-    if (error.response.status == 401) {
+    if (error.response.status === 401) {
       this.handleAuthFailure(error);
     }
   }
@@ -180,7 +180,7 @@ export default class AdminDashboard extends React.Component {
   handleGetAuthStatusFailure(error) {
     console.log(error);
     this.setState({ self: {} });
-    if (error.response.status == 401) {
+    if (error.response.status === 401) {
       this.handleAuthFailure(error);
     }
   }
@@ -247,7 +247,7 @@ export default class AdminDashboard extends React.Component {
 
   handleCreateUserFailure(error) {
     console.log(error);
-    if (error.response.status == 401) {
+    if (error.response.status === 401) {
       this.handleAuthFailure(error);
     }
   }
@@ -290,7 +290,7 @@ export default class AdminDashboard extends React.Component {
 
   handleUpdateUserFailure(error) {
     console.log(error);
-    if (error.response.status == 401) {
+    if (error.response.status === 401) {
       this.handleAuthFailure(error);
     }
   }
@@ -315,7 +315,7 @@ export default class AdminDashboard extends React.Component {
 
   handleRemoveUserFailure(error) {
     console.log(error);
-    if (error.response.status == 401) {
+    if (error.response.status === 401) {
       this.handleAuthFailure(error);
     }
   }
@@ -337,7 +337,7 @@ export default class AdminDashboard extends React.Component {
   }
 
   handleDownloadProfileFailure(error) {
-    if ("response" in error && error.response.status == 401) {
+    if ("response" in error && error.response.status === 401) {
       this.handleAuthFailure(error);
     }
     console.log(error);
@@ -359,7 +359,7 @@ export default class AdminDashboard extends React.Component {
   }
 
   handleDefineNetworkFailure(error) {
-    if ("response" in error && error.response.status == 401) {
+    if ("response" in error && error.response.status === 401) {
       this.handleAuthFailure(error);
     }
     console.log(error);
@@ -380,7 +380,7 @@ export default class AdminDashboard extends React.Component {
   }
 
   handleUndefineNetworkFailure(error) {
-    if ("response" in error && error.response.status == 401) {
+    if ("response" in error && error.response.status === 401) {
       this.handleAuthFailure(error);
     }
     console.log(error);
@@ -469,7 +469,7 @@ export default class AdminDashboard extends React.Component {
   }
 
   handleAssociateUserFailure(error) {
-    if ("response" in error && error.response.status == 401) {
+    if ("response" in error && error.response.status === 401) {
       this.handleAuthFailure(error);
     }
     console.log(error);
@@ -480,7 +480,7 @@ export default class AdminDashboard extends React.Component {
   }
 
   handleDissociateUserFailure(error) {
-    if ("response" in error && error.response.status == 401) {
+    if ("response" in error && error.response.status === 401) {
       this.handleAuthFailure(error);
     }
     console.log(error);
@@ -495,7 +495,7 @@ export default class AdminDashboard extends React.Component {
         this.refresh();
       }.bind(this),
       function() {
-        if ("response" in error && error.response.status == 401) {
+        if ("response" in error && error.response.status === 401) {
           this.handleAuthFailure(error);
         }
         console.log(error);
@@ -514,9 +514,9 @@ export default class AdminDashboard extends React.Component {
     }
 
     let users = [];
-    for (var i = 0; i < this.state.users.length; i++) {
+    for (let i = 0; i < this.state.users.length; i++) {
       let isStatic = "";
-      if (this.state.users[i].host_id != 0) {
+      if (this.state.users[i].host_id !== 0) {
         isStatic = (
           <small>
             <span
@@ -661,12 +661,12 @@ export default class AdminDashboard extends React.Component {
     }
 
     let networks = [];
-    for (var i = 0; i < this.state.networks.length; i++) {
+    for (let i = 0; i < this.state.networks.length; i++) {
       let via;
-      if (this.state.networks[i].type == "ROUTE") {
+      if (this.state.networks[i].type === "ROUTE") {
         via = "via vpn-server";
 
-        if (this.state.networks[i].via && this.state.networks[i].via != "") {
+        if (this.state.networks[i].via && this.state.networks[i].via !== "") {
           via = "via " + this.state.networks[i].via;
         }
       }
@@ -756,10 +756,10 @@ export default class AdminDashboard extends React.Component {
                 isAdmin={this.state.editedUser.is_admin}
                 pushGW={!this.state.editedUser.no_gw}
                 ipAllocationMethod={
-                  this.state.editedUser.host_id == 0 ? "dynamic" : "static"
+                  this.state.editedUser.host_id === 0 ? "dynamic" : "static"
                 }
                 staticIP={
-                  this.state.editedUser.host_id == 0
+                  this.state.editedUser.host_id === 0
                     ? ""
                     : num2dot(this.state.editedUser.host_id)
                 }

+ 156 - 123
webui/ovpm/src/components/Dashboard/UserDashboard/index.jsx

@@ -1,132 +1,165 @@
-import React from 'react';
-import { Link } from 'react-router-dom'
-import Panel from 'muicss/lib/react/panel';
-import Button from 'muicss/lib/react/button';
-import Container from 'muicss/lib/react/container';
-
-import {GetAuthToken, ClearAuthToken} from '../../../utils/auth.js';
-import {API} from '../../../utils/restClient.js';
-import {baseURL, endpoints} from '../../../api.js';
-
-import Modal from 'react-modal';
-import PasswordEdit from './PasswordEdit';
-
-let saveData = (function () {
-    var a = document.createElement("a");
-    document.body.appendChild(a);
-    a.style = "display: none";
-    return function (data, fileName) {
-        var json = data,
-            blob = new Blob([json], {type: "octet/stream"}),
-            url = window.URL.createObjectURL(blob);
-        a.href = url;
-        a.download = fileName;
-        a.click();
-        window.URL.revokeObjectURL(url);
-    };
-}());
+import React from "react";
+import { Link } from "react-router-dom";
+import Panel from "muicss/lib/react/panel";
+import Button from "muicss/lib/react/button";
+import Container from "muicss/lib/react/container";
+
+import { GetAuthToken, ClearAuthToken } from "../../../utils/auth.js";
+import { API } from "../../../utils/restClient.js";
+import { baseURL, endpoints } from "../../../api.js";
+
+import Modal from "react-modal";
+import PasswordEdit from "./PasswordEdit";
+
+let saveData = (function() {
+  var a = document.createElement("a");
+  document.body.appendChild(a);
+  a.style = "display: none";
+  return function(data, fileName) {
+    var json = data,
+      blob = new Blob([json], { type: "octet/stream" }),
+      url = window.URL.createObjectURL(blob);
+    a.href = url;
+    a.download = fileName;
+    a.click();
+    window.URL.revokeObjectURL(url);
+  };
+})();
 
 const modalStyle = {
-    content : {
-        top                   : '50%',
-        left                  : '50%',
-        right                 : 'auto',
-        bottom                : 'auto',
-        marginRight           : '-50%',
-        transform             : 'translate(-50%, -50%)'
-    }
+  content: {
+    top: "50%",
+    left: "50%",
+    right: "auto",
+    bottom: "auto",
+    marginRight: "-50%",
+    transform: "translate(-50%, -50%)"
+  }
 };
 
-
 export default class UserDashboard extends React.Component {
-    constructor(props) {
-        super(props)
-
-        this.state = {
-            isChangePasswordModalOpen: false,
-        }
-        let authToken = GetAuthToken()
-        this.api = new API(baseURL, endpoints, authToken)
-    }
-
-    componentWillMount() {
-    }
-
-    handleDownloadProfileClick(e) {
-        this.props.api.call("genConfig", {username: this.props.username}, true, this.handleDownloadProfileSuccess.bind(this), this.handleDownloadProfileFailure.bind(this))
-    }
-
-    handleDownloadProfileSuccess(res) {
-        let blob = res.data.client_config
-        saveData(blob, this.props.username+".ovpn")
-    }
-
-    handleDownloadProfileFailure(error) {
-        if (error.response.status == 401) {
-            this.handleAuthFailure(error)
-        }
-        console.log(error)
-    }
-
-    handleAuthFailure(error) {
-        console.log("auth failure", error)
-        ClearAuthToken()
-    }
+  constructor(props) {
+    super(props);
 
-    handleCloseModal() {
-        this.setState({isChangePasswordModalOpen: false})
-    }
-    handleOpenChangePasswordModal() {
-        this.setState({isChangePasswordModalOpen: true})
-    }
-
-    handleChangePasswordSave(password) {
-        let userObj = {
-            username: this.props.username,
-            password: password,
-        }
-        this.api.call("userUpdate", userObj, true, this.handleChangePasswordSuccess.bind(this), this.handleChangePasswordFailure.bind(this))
-        this.handleCloseChangePasswordModal()
-    }
-
-    handleChangePasswordSuccess(res) {
-        console.log("password changed")
-    }
-
-    handleChangePasswordFailure(error) {
-        console.log(error)
-        if (error.response.status == 401) {
-            this.handleAuthFailure(error)
-        }
-    }
-
-    handleAuthFailure(error) {
-        console.log("auth failure", error)
-        ClearAuthToken()
-    }
-
-    handleCloseChangePasswordModal() {
-        this.setState({isChangePasswordModalOpen: false})
+    this.state = {
+      isChangePasswordModalOpen: false
+    };
+    let authToken = GetAuthToken();
+    this.api = new API(baseURL, endpoints, authToken);
+  }
+
+  componentWillMount() {}
+
+  handleDownloadProfileClick(e) {
+    this.props.api.call(
+      "genConfig",
+      { username: this.props.username },
+      true,
+      this.handleDownloadProfileSuccess.bind(this),
+      this.handleDownloadProfileFailure.bind(this)
+    );
+  }
+
+  handleDownloadProfileSuccess(res) {
+    let blob = res.data.client_config;
+    saveData(blob, this.props.username + ".ovpn");
+  }
+
+  handleDownloadProfileFailure(error) {
+    if (error.response.status === 401) {
+      this.handleAuthFailure(error);
     }
-
-    render() {
-        let passwordResetModal = (
-            <Modal isOpen={this.state.isChangePasswordModalOpen} contentLabel="Modal" style={modalStyle}>
-                <PasswordEdit title="Change Password" onCancel={this.handleCloseChangePasswordModal.bind(this)} onSave={this.handleChangePasswordSave.bind(this)} />
-            </Modal>
-        )
-
-        return (
-            <Container style={{"padding-top":"5%"}}>
-                {passwordResetModal}
-                <Panel>
-                    <p>Welcome, <b>{this.props.username}</b> (<Link to="/logout">logout</Link>)!</p>
-                    <div>
-                        <Button color="primary" variant="raised" onClick={this.handleOpenChangePasswordModal.bind(this)}>Change Password</Button>
-                        <Button color="primary" variant="raised" onClick={this.handleDownloadProfileClick.bind(this)}>Download VPN Profile</Button>
-                    </div>
-                </Panel>
-            </Container>
-        )
+    console.log(error);
+  }
+
+  handleAuthFailure(error) {
+    console.log("auth failure", error);
+    ClearAuthToken();
+  }
+
+  handleCloseModal() {
+    this.setState({ isChangePasswordModalOpen: false });
+  }
+  handleOpenChangePasswordModal() {
+    this.setState({ isChangePasswordModalOpen: true });
+  }
+
+  handleChangePasswordSave(password) {
+    let userObj = {
+      username: this.props.username,
+      password: password
+    };
+    this.api.call(
+      "userUpdate",
+      userObj,
+      true,
+      this.handleChangePasswordSuccess.bind(this),
+      this.handleChangePasswordFailure.bind(this)
+    );
+    this.handleCloseChangePasswordModal();
+  }
+
+  handleChangePasswordSuccess(res) {
+    console.log("password changed");
+  }
+
+  handleChangePasswordFailure(error) {
+    console.log(error);
+    if (error.response.status === 401) {
+      this.handleAuthFailure(error);
     }
+  }
+
+  // handleAuthFailure(error) {
+  //     console.log("auth failure", error)
+  //     ClearAuthToken()
+  // }
+
+  handleCloseChangePasswordModal() {
+    this.setState({ isChangePasswordModalOpen: false });
+  }
+
+  render() {
+    let passwordResetModal = (
+      <Modal
+        isOpen={this.state.isChangePasswordModalOpen}
+        contentLabel="Modal"
+        style={modalStyle}
+      >
+        <PasswordEdit
+          title="Change Password"
+          onCancel={this.handleCloseChangePasswordModal.bind(this)}
+          onSave={this.handleChangePasswordSave.bind(this)}
+        />
+      </Modal>
+    );
+
+    return (
+      <Container style={{ "padding-top": "5%" }}>
+        {passwordResetModal}
+        <Panel>
+          <p>
+            Welcome, <b>{this.props.username}</b> (
+            <Link to="/logout">logout</Link>)!
+          </p>
+          <div>
+            <Button
+              color="primary"
+              variant="raised"
+              onClick={this.handleOpenChangePasswordModal.bind(this)}
+            >
+              Change Password
+            </Button>
+            <Button
+              color="primary"
+              variant="raised"
+              onClick={this.handleDownloadProfileClick.bind(this)}
+            >
+              Download VPN Profile
+            </Button>
+          </div>
+        </Panel>
+      </Container>
+    );
+  }
 }

+ 51 - 47
webui/ovpm/src/components/Dashboard/index.jsx

@@ -1,60 +1,64 @@
-import React from 'react';
-
-import {GetAuthToken, ClearAuthToken} from '../../utils/auth.js';
-import {API} from '../../utils/restClient.js';
-import {baseURL, endpoints} from '../../api.js';
-import UserDashboard from './UserDashboard'
-import AdminDashboard from './AdminDashboard'
+import React from "react";
 
+import { GetAuthToken, ClearAuthToken } from "../../utils/auth.js";
+import { API } from "../../utils/restClient.js";
+import { baseURL, endpoints } from "../../api.js";
+import UserDashboard from "./UserDashboard";
+import AdminDashboard from "./AdminDashboard";
 
 export default class Dashboard extends React.Component {
-    constructor(props) {
-        super(props)
-
-        this.state = {
-            username: "",
-            isAdmin: false,
-        }
-        let authToken = GetAuthToken()
-        this.api = new API(baseURL, endpoints, authToken)
-    }
+  constructor(props) {
+    super(props);
 
-    handleGetUserSuccess(res) {
-        this.setState({
-            username: res.data.user.username,
-            isAdmin: res.data.user.is_admin,
-        })
-    }
+    this.state = {
+      username: "",
+      isAdmin: false
+    };
+    let authToken = GetAuthToken();
+    this.api = new API(baseURL, endpoints, authToken);
+  }
 
-    componentWillMount() {
-        this.api.call("authStatus", {}, true, this.handleGetUserSuccess.bind(this), this.handleGetUserFailure.bind(this))
-    }
+  handleGetUserSuccess(res) {
+    this.setState({
+      username: res.data.user.username,
+      isAdmin: res.data.user.is_admin
+    });
+  }
 
-    handleGetUserFailure(error) {
-        if (error.response.status == 401) {
-            this.handleAuthFailure(error)
-        }
+  componentWillMount() {
+    this.api.call(
+      "authStatus",
+      {},
+      true,
+      this.handleGetUserSuccess.bind(this),
+      this.handleGetUserFailure.bind(this)
+    );
+  }
 
-        console.log("get user failure", error)
+  handleGetUserFailure(error) {
+    if (error.response.status === 401) {
+      this.handleAuthFailure(error);
     }
 
-    handleAuthFailure(error) {
-        console.log("auth failure", error)
-        ClearAuthToken()
+    console.log("get user failure", error);
+  }
 
-    }
+  handleAuthFailure(error) {
+    console.log("auth failure", error);
+    ClearAuthToken();
+  }
 
-    render() {
-        let dashboard
-        if (!this.state.isAdmin) {
-            dashboard = <UserDashboard username={this.state.username} api={this.api} />
-        } else {
-            dashboard = <AdminDashboard username={this.state.username} api={this.api} />
-        }
-        return (
-            <div className="mui--text-center">
-                {dashboard}
-            </div>
-        )
+  render() {
+    let dashboard;
+    if (!this.state.isAdmin) {
+      dashboard = (
+        <UserDashboard username={this.state.username} api={this.api} />
+      );
+    } else {
+      dashboard = (
+        <AdminDashboard username={this.state.username} api={this.api} />
+      );
     }
+    return <div className="mui--text-center">{dashboard}</div>;
+  }
 }

+ 1 - 1
webui/ovpm/src/components/Master/index.jsx

@@ -1,5 +1,5 @@
 import React from "react";
-import style from "./style.css";
+import "./style.css";
 
 import { BrowserRouter as Router, Route, Redirect } from "react-router-dom";
 

+ 21 - 21
webui/ovpm/src/utils/auth.js

@@ -1,38 +1,38 @@
-const storage = sessionStorage
-const prefix = "ovpm_auth_"
+const storage = sessionStorage;
+const prefix = "ovpm_auth_";
 export function GetAuthToken() {
-    let key = storage.getItem("authKey")
-    if (!key) {
-        return ""
-    }
-    return key
+  let key = storage.getItem("authKey");
+  if (!key) {
+    return "";
+  }
+  return key;
 }
 
 export function SetAuthToken(token) {
-    return storage.setItem("authKey", token)
+  return storage.setItem("authKey", token);
 }
 
 export function ClearAuthToken() {
-    storage.removeItem("authKey")
+  storage.removeItem("authKey");
 }
 
 export function IsAuthenticated() {
-    if (GetAuthToken() != "") {
-        return true
-    }
-    return false
+  if (GetAuthToken() !== "") {
+    return true;
+  }
+  return false;
 }
 
 export function SetItem(key, value) {
-    if (key.constructor === String) {
-        return storage.setItem(JSON.stringify(prefix+key), JSON.stringify(value))
-    }
-    throw "key should be a string: " + key
+  if (key.constructor === String) {
+    return storage.setItem(JSON.stringify(prefix + key), JSON.stringify(value));
+  }
+  throw new Error("key should be a string: " + key);
 }
 
 export function GetItem(key) {
-    if (key.constructor === String) {
-        return JSON.parse(storage.getItem(JSON.stringify(prefix+key)))
-    }
-    throw "key should be a string: " + key
+  if (key.constructor === String) {
+    return JSON.parse(storage.getItem(JSON.stringify(prefix + key)));
+  }
+  throw new Error("key should be a string: " + key);
 }

+ 16 - 10
webui/ovpm/src/utils/restClient.js

@@ -13,19 +13,23 @@ export class API {
 
     // validate endpoints
     if (this.endpoints.constructor !== Object) {
-      throw "endpoints must be an object: " + this.baseURL;
+      throw new Error("endpoints must be an object: " + this.baseURL);
     } else {
       for (let endpointName in this.endpoints) {
         if (endpoints[endpointName].constructor !== Object) {
-          throw "items of 'endpoints' should be endpoint object: " +
-            endpoints[endpointName];
+          throw new Error(
+            "items of 'endpoints' should be endpoint object: " +
+              endpoints[endpointName]
+          );
         }
 
         let keysShouldExist = ["path", "method"];
         for (let key in keysShouldExist) {
           if (!(keysShouldExist[key] in endpoints[endpointName])) {
-            throw "endpoint object should have a key called: " +
-              keysShouldExist[key];
+            throw new Error(
+              "endpoint object should have a key called: " +
+                keysShouldExist[key]
+            );
           }
           if (
             !(
@@ -33,8 +37,10 @@ export class API {
               String
             )
           ) {
-            throw "endpoint object should have a key called: " +
-              keysShouldExist[key];
+            throw new Error(
+              "endpoint object should have a key called: " +
+                keysShouldExist[key]
+            );
           }
         }
       }
@@ -42,14 +48,14 @@ export class API {
 
     // validate authToken
     if (this.authToken && this.authToken.constructor !== String) {
-      throw "authToken should be a string: " + this.authToken;
+      throw new Error("authToken should be a string: " + this.authToken);
     }
   }
 
   // setAuthToken receives and stores an Authorization Token
   setAuthToken(authToken) {
     if (authToken.constructor !== String) {
-      throw "authToken should be a string: " + authToken;
+      throw new Error("authToken should be a string: " + authToken);
     }
     this.authToken = authToken;
   }
@@ -65,7 +71,7 @@ export class API {
   call(endpointName, data, performAuth, onSuccess, onFailure) {
     // validate endpointName
     if (!(endpointName in this.endpoints)) {
-      throw endpointName + " is not available in " + this.endpoints;
+      throw new Error(endpointName + " is not available in " + this.endpoints);
     }
 
     let endpoint = this.endpoints[endpointName];