Skip to content

Commit

Permalink
dgtown/auth 2 (#4595)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-g-town authored May 2, 2024
1 parent 64a9add commit dbd715a
Show file tree
Hide file tree
Showing 13 changed files with 299 additions and 289 deletions.
1 change: 0 additions & 1 deletion api/server/router/addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,5 @@ func getAddonRoutes(

var routes []*router.Route


return routes, newPath
}
7 changes: 1 addition & 6 deletions dashboard/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,7 @@
],
"@typesecript-eslint/consistent-type-imports": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksVoidReturn": false
}
],
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-floating-promises": [
"error",
{
Expand Down
251 changes: 36 additions & 215 deletions dashboard/src/main/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component } from "react";
import React, { useContext, useEffect, useState } from "react";
import { Redirect, Route, Switch } from "react-router-dom";

import Loading from "components/Loading";
Expand All @@ -7,249 +7,72 @@ import api from "shared/api";
import { Context } from "shared/Context";
import { PorterUrls, type PorterUrl } from "shared/routing";

import Login from "./auth/Login";
import Register from "./auth/Register";
import ResetPasswordFinalize from "./auth/ResetPasswordFinalize";
import ResetPasswordInit from "./auth/ResetPasswordInit";
import SetInfo from "./auth/SetInfo";
import VerifyEmail from "./auth/VerifyEmail";
import { useAuthn } from "../shared/auth/AuthnContext";
import CurrentError from "./CurrentError";
import Home from "./home/Home";

type PropsType = {};

type StateType = {
loading: boolean;
isLoggedIn: boolean;
isEmailVerified: boolean;
hasInfo: boolean;
initialized: boolean;
local: boolean;
userId: number;
version: string;
};

export default class Main extends Component<PropsType, StateType> {
state = {
loading: true,
isLoggedIn: false,
isEmailVerified: false,
hasInfo: false,
initialized: localStorage.getItem("init") === "true",
local: false,
userId: null as number,
version: null as string,
};

componentDidMount() {
const Main: React.FC<PropsType> = () => {
const {
currentError,
setCurrentError,
setEdition,
setEnableGitlab,
currentProject,
currentCluster,
} = useContext(Context);
const { handleLogOut } = useAuthn();
const [version, setVersion] = useState("");

useEffect(() => {
// Get capabilities to case on user info requirements
api
.getMetadata("", {}, {})
.then((res) => {
this.setState({
version: res.data?.version,
});
setVersion(res.data?.version);
})
.catch((err) => {
console.log(err);
});
.catch(() => {});

const { setUser, setCurrentError } = this.context;
const urlParams = new URLSearchParams(window.location.search);
const error = urlParams.get("error");
error && setCurrentError(error);
api
.checkAuth("", {}, {})
.then((res) => {
if (res?.data) {
setUser(res.data.id, res.data.email);
this.setState({
isLoggedIn: true,
isEmailVerified: res.data.email_verified,
initialized: true,
hasInfo: res.data.company_name && true,
loading: false,
userId: res.data.id,
});
} else {
this.setState({ isLoggedIn: false, loading: false });
}
})
.catch((err) => {
this.setState({ isLoggedIn: false, loading: false });
});

api
.getMetadata("", {}, {})
.then((res) => {
this.context.setEdition(res.data?.version);
this.setState({ local: !res.data?.provisioner });
this.context.setEnableGitlab(!!res.data?.gitlab);
setEdition(res.data?.version);
setEnableGitlab(!!res.data?.gitlab);
})
.catch((err) => {
console.log(err);
});
}
.catch(() => {});
}, []);

initialize = () => {
this.setState({ isLoggedIn: true, initialized: true });
localStorage.setItem("init", "true");
};

authenticate = () => {
api
.checkAuth("", {}, {})
.then((res) => {
if (res?.data) {
this.context.setUser(res?.data?.id, res?.data?.email);
this.setState({
isLoggedIn: true,
isEmailVerified: res?.data?.email_verified,
initialized: true,
hasInfo: res.data.company_name && true,
loading: false,
userId: res.data.id,
});
} else {
this.setState({ isLoggedIn: false, loading: false });
}
})
.catch((err) => {
this.setState({ isLoggedIn: false, loading: false });
});
};

handleLogOut = () => {
// Clears local storage for proper rendering of clusters
// Attempt user logout
api
.logOutUser("<token>", {}, {})
.then(() => {
this.context.clearContext();
this.setState({ isLoggedIn: false, initialized: true });
localStorage.clear();
})
.catch((err) =>
this.context.setCurrentError(err.response?.data.errors[0])
);
};

renderMain = () => {
if (this.state.loading || !this.state.version) {
const renderMain = (): JSX.Element => {
if (!version) {
return <Loading />;
}

// if logged in but not verified, block until email verification
if (
!this.state.local &&
this.state.isLoggedIn &&
!this.state.isEmailVerified
) {
return (
<Switch>
<Route
path="/"
render={() => {
return <VerifyEmail handleLogOut={this.handleLogOut} />;
}}
/>
</Switch>
);
}

// Handle case where new user signs up via OAuth and has not set name and company
if (
this.state.version === "production" &&
!this.state.hasInfo &&
this.state.userId > 9312 &&
this.state.isLoggedIn
) {
return (
<Switch>
<Route
path="/"
render={() => {
return (
<SetInfo
handleLogOut={this.handleLogOut}
authenticate={this.authenticate}
/>
);
}}
/>
</Switch>
);
}

return (
<Switch>
<Route
path="/login"
render={() => {
if (!this.state.isLoggedIn) {
return <Login authenticate={this.authenticate} />;
} else {
return <Redirect to="/" />;
}
}}
/>
<Route
path="/register"
render={() => {
if (!this.state.isLoggedIn) {
return <Register authenticate={this.authenticate} />;
} else {
return <Redirect to="/" />;
}
}}
/>
<Route
path="/password/reset/finalize"
render={() => {
if (!this.state.isLoggedIn) {
return <ResetPasswordFinalize />;
} else {
return <Redirect to="/" />;
}
}}
/>
<Route
path="/password/reset"
render={() => {
if (!this.state.isLoggedIn) {
return <ResetPasswordInit />;
} else {
return <Redirect to="/" />;
}
}}
/>
<Route
exact
path="/"
render={() => {
if (this.state.isLoggedIn) {
return <Redirect to="/dashboard" />;
} else {
return <Redirect to="/login" />;
}
return <Redirect to="/dashboard" />;
}}
/>
<Route
path={`/:baseRoute/:cluster?/:namespace?`}
render={(routeProps) => {
const baseRoute = routeProps.match.params.baseRoute;
if (
this.state.isLoggedIn &&
this.state.initialized &&
PorterUrls.includes(baseRoute)
) {
if (PorterUrls.includes(baseRoute)) {
return (
<Home
key="home"
currentProject={this.context.currentProject}
currentCluster={this.context.currentCluster}
currentProject={currentProject}
currentCluster={currentCluster}
currentRoute={baseRoute as PorterUrl}
logOut={this.handleLogOut}
logOut={handleLogOut}
/>
);
} else {
Expand All @@ -261,14 +84,12 @@ export default class Main extends Component<PropsType, StateType> {
);
};

render() {
return (
<>
{this.renderMain()}
<CurrentError currentError={this.context.currentError} />
</>
);
}
}
return (
<>
{renderMain()}
<CurrentError currentError={currentError} />
</>
);
};

Main.contextType = Context;
export default Main;
33 changes: 16 additions & 17 deletions dashboard/src/main/MainWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import React, { Component } from "react";
import React from "react";
import { withRouter, type RouteComponentProps } from "react-router";

import AuthzProvider from "shared/auth/AuthzContext";
import MainWrapperErrorBoundary from "shared/error_handling/MainWrapperErrorBoundary";

import AuthnProvider from "../shared/auth/AuthnContext";
import { ContextProvider } from "../shared/Context";
import Main from "./Main";
import { RouteComponentProps, withRouter } from "react-router";
import AuthProvider from "shared/auth/AuthContext";
import MainWrapperErrorBoundary from "shared/error_handling/MainWrapperErrorBoundary";

type PropsType = RouteComponentProps & {};

type StateType = {};

class MainWrapper extends Component<PropsType, StateType> {
render() {
let { history, location } = this.props;
return (
<ContextProvider history={history} location={location}>
<AuthProvider>
const MainWrapper: React.FC<PropsType> = ({ history, location }) => {
return (
<ContextProvider history={history} location={location}>
<AuthzProvider>
<AuthnProvider>
<MainWrapperErrorBoundary>
<Main />
</MainWrapperErrorBoundary>
</AuthProvider>
</ContextProvider>
);
}
}
</AuthnProvider>
</AuthzProvider>
</ContextProvider>
);
};

export default withRouter(MainWrapper);
4 changes: 2 additions & 2 deletions dashboard/src/main/auth/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import GoogleIcon from "assets/GoogleIcon";
import logo from "assets/logo.png";

type Props = {
authenticate: () => void;
authenticate: () => Promise<void>;
};

const getWindowDimensions = () => {
Expand Down Expand Up @@ -56,7 +56,7 @@ const Login: React.FC<Props> = ({ authenticate }) => {
window.location.href = res.data.redirect;
} else {
setUser(res?.data?.id, res?.data?.email);
authenticate();
authenticate().catch(() => {});
}
})
.catch((err) => {
Expand Down
Loading

0 comments on commit dbd715a

Please sign in to comment.