feat: redirect after login when applicable
This commit is contained in:
parent
04c12e4da9
commit
e2634dc490
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Switch, Route, useHistory } from 'react-router-dom';
|
import { Switch, Route, useHistory, useLocation, Redirect } from 'react-router-dom';
|
||||||
import * as H from 'history';
|
import * as H from 'history';
|
||||||
|
|
||||||
import Dashboard from 'Dashboard';
|
import Dashboard from 'Dashboard';
|
||||||
@ -29,8 +29,27 @@ type ValidateTokenResponse = {
|
|||||||
userID: string;
|
userID: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AuthorizedRoutes = () => {
|
const UserRequiredRoute: React.FC<any> = ({ children }) => {
|
||||||
const history = useHistory();
|
const { user } = useCurrentUser();
|
||||||
|
const location = useLocation();
|
||||||
|
if (user) {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Redirect
|
||||||
|
to={{
|
||||||
|
pathname: '/login',
|
||||||
|
state: { redirect: location.pathname },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type RoutesProps = {
|
||||||
|
history: H.History;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Routes: React.FC<RoutesProps> = () => {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const { setUser } = useCurrentUser();
|
const { setUser } = useCurrentUser();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -38,7 +57,6 @@ const AuthorizedRoutes = () => {
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
}).then(async x => {
|
}).then(async x => {
|
||||||
const { status } = x;
|
|
||||||
const response: ValidateTokenResponse = await x.json();
|
const response: ValidateTokenResponse = await x.json();
|
||||||
const { valid, userID } = response;
|
const { valid, userID } = response;
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@ -47,32 +65,28 @@ const AuthorizedRoutes = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
return loading ? null : (
|
if (loading) return null;
|
||||||
<Switch>
|
return (
|
||||||
<MainContent>
|
|
||||||
<Route exact path="/" component={Dashboard} />
|
|
||||||
<Route exact path="/projects" component={Projects} />
|
|
||||||
<Route path="/projects/:projectID" component={Project} />
|
|
||||||
<Route path="/teams/:teamID" component={Teams} />
|
|
||||||
<Route path="/profile" component={Profile} />
|
|
||||||
<Route path="/admin" component={Admin} />
|
|
||||||
<Route path="/tasks" component={MyTasks} />
|
|
||||||
</MainContent>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type RoutesProps = {
|
|
||||||
history: H.History;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Routes: React.FC<RoutesProps> = () => (
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/login" component={Login} />
|
<Route exact path="/login" component={Login} />
|
||||||
<Route exact path="/register" component={Register} />
|
<Route exact path="/register" component={Register} />
|
||||||
<Route exact path="/confirm" component={Confirm} />
|
<Route exact path="/confirm" component={Confirm} />
|
||||||
<AuthorizedRoutes />
|
<Switch>
|
||||||
|
<MainContent>
|
||||||
|
<Route path="/projects/:projectID" component={Project} />
|
||||||
|
|
||||||
|
<UserRequiredRoute>
|
||||||
|
<Route exact path="/" component={Dashboard} />
|
||||||
|
<Route exact path="/projects" component={Projects} />
|
||||||
|
<Route path="/teams/:teamID" component={Teams} />
|
||||||
|
<Route path="/profile" component={Profile} />
|
||||||
|
<Route path="/admin" component={Admin} />
|
||||||
|
<Route path="/tasks" component={MyTasks} />
|
||||||
|
</UserRequiredRoute>
|
||||||
|
</MainContent>
|
||||||
|
</Switch>
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default Routes;
|
export default Routes;
|
||||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import TopNavbar, { MenuItem } from 'shared/components/TopNavbar';
|
import TopNavbar, { MenuItem } from 'shared/components/TopNavbar';
|
||||||
import LoggedOutNavbar from 'shared/components/TopNavbar/LoggedOut';
|
import LoggedOutNavbar from 'shared/components/TopNavbar/LoggedOut';
|
||||||
import { ProfileMenu } from 'shared/components/DropdownMenu';
|
import { ProfileMenu } from 'shared/components/DropdownMenu';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory, useRouteMatch } from 'react-router';
|
||||||
import { useCurrentUser } from 'App/context';
|
import { useCurrentUser } from 'App/context';
|
||||||
import { RoleCode, useTopNavbarQuery } from 'shared/generated/graphql';
|
import { RoleCode, useTopNavbarQuery } from 'shared/generated/graphql';
|
||||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||||
@ -234,6 +234,7 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({
|
|||||||
onRemoveFromBoard,
|
onRemoveFromBoard,
|
||||||
}) => {
|
}) => {
|
||||||
const { user } = useCurrentUser();
|
const { user } = useCurrentUser();
|
||||||
|
const match = useRouteMatch();
|
||||||
if (user) {
|
if (user) {
|
||||||
return (
|
return (
|
||||||
<LoggedInNavbar
|
<LoggedInNavbar
|
||||||
@ -255,7 +256,7 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <LoggedOutNavbar name={name} menuType={menuType} />;
|
return <LoggedOutNavbar match={match.url} name={name} menuType={menuType} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GlobalTopNavbar;
|
export default GlobalTopNavbar;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, useContext } from 'react';
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory, useLocation } from 'react-router';
|
||||||
import Login from 'shared/components/Login';
|
import Login from 'shared/components/Login';
|
||||||
import UserContext from 'App/context';
|
import UserContext from 'App/context';
|
||||||
import { Container, LoginWrapper } from './Styles';
|
import { Container, LoginWrapper } from './Styles';
|
||||||
@ -7,6 +7,7 @@ import { Container, LoginWrapper } from './Styles';
|
|||||||
const Auth = () => {
|
const Auth = () => {
|
||||||
const [invalidLoginAttempt, setInvalidLoginAttempt] = useState(0);
|
const [invalidLoginAttempt, setInvalidLoginAttempt] = useState(0);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const location = useLocation<{ redirect: string } | undefined>();
|
||||||
const { setUser } = useContext(UserContext);
|
const { setUser } = useContext(UserContext);
|
||||||
const login = (
|
const login = (
|
||||||
data: LoginFormData,
|
data: LoginFormData,
|
||||||
@ -30,8 +31,12 @@ const Auth = () => {
|
|||||||
const response = await x.json();
|
const response = await x.json();
|
||||||
const { userID } = response;
|
const { userID } = response;
|
||||||
setUser(userID);
|
setUser(userID);
|
||||||
|
if (location.state && location.state.redirect) {
|
||||||
|
history.push(location.state.redirect);
|
||||||
|
} else {
|
||||||
history.push('/');
|
history.push('/');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,9 +12,10 @@ export type MenuItem = {
|
|||||||
type NavBarProps = {
|
type NavBarProps = {
|
||||||
menuType?: Array<MenuItem> | null;
|
menuType?: Array<MenuItem> | null;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
|
match: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NavBar: React.FC<NavBarProps> = ({ menuType, name }) => {
|
const NavBar: React.FC<NavBarProps> = ({ menuType, name, match }) => {
|
||||||
return (
|
return (
|
||||||
<S.NavbarWrapper>
|
<S.NavbarWrapper>
|
||||||
<S.NavbarHeader>
|
<S.NavbarHeader>
|
||||||
@ -51,7 +52,12 @@ const NavBar: React.FC<NavBarProps> = ({ menuType, name }) => {
|
|||||||
<S.TaskcafeTitle>Taskcafé</S.TaskcafeTitle>
|
<S.TaskcafeTitle>Taskcafé</S.TaskcafeTitle>
|
||||||
</S.LogoContainer>
|
</S.LogoContainer>
|
||||||
<S.GlobalActions>
|
<S.GlobalActions>
|
||||||
<Link to="/login">
|
<Link
|
||||||
|
to={{
|
||||||
|
pathname: '/login',
|
||||||
|
state: { redirect: match },
|
||||||
|
}}
|
||||||
|
>
|
||||||
<S.SignIn>Sign In</S.SignIn>
|
<S.SignIn>Sign In</S.SignIn>
|
||||||
</Link>
|
</Link>
|
||||||
</S.GlobalActions>
|
</S.GlobalActions>
|
||||||
|
@ -33,24 +33,19 @@ func NewHandler(repo db.Repository, emailConfig utils.EmailConfig) http.Handler
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
c.Directives.HasRole = func(ctx context.Context, obj interface{}, next graphql.Resolver, roles []RoleLevel, level ActionLevel, typeArg ObjectType) (interface{}, error) {
|
c.Directives.HasRole = func(ctx context.Context, obj interface{}, next graphql.Resolver, roles []RoleLevel, level ActionLevel, typeArg ObjectType) (interface{}, error) {
|
||||||
/*
|
userID, ok := GetUser(ctx)
|
||||||
TODO: add permission check
|
|
||||||
role, ok := GetUserRole(ctx)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("user ID is missing")
|
return nil, errors.New("user must be logged in")
|
||||||
}
|
}
|
||||||
if role == "admin" {
|
user, err := repo.GetUserAccountByID(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if user.RoleCode == "admin" {
|
||||||
return next(ctx)
|
return next(ctx)
|
||||||
} else if level == ActionLevelOrg {
|
} else if level == ActionLevelOrg {
|
||||||
return nil, errors.New("must be an org admin")
|
return nil, errors.New("must be an org admin")
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
userID, ok := GetUserID(ctx)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("user must be logged in")
|
|
||||||
}
|
|
||||||
log.Info("has role")
|
|
||||||
|
|
||||||
var subjectID uuid.UUID
|
var subjectID uuid.UUID
|
||||||
in := graphql.GetFieldContext(ctx).Args["input"]
|
in := graphql.GetFieldContext(ctx).Args["input"]
|
||||||
@ -90,7 +85,6 @@ func NewHandler(repo db.Repository, emailConfig utils.EmailConfig) http.Handler
|
|||||||
return nil, errors.New("error while casting subject uuid")
|
return nil, errors.New("error while casting subject uuid")
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
if level == ActionLevelProject {
|
if level == ActionLevelProject {
|
||||||
logger.New(ctx).WithFields(log.Fields{"subjectID": subjectID}).Info("fetching subject ID by typeArg")
|
logger.New(ctx).WithFields(log.Fields{"subjectID": subjectID}).Info("fetching subject ID by typeArg")
|
||||||
if typeArg == ObjectTypeTask {
|
if typeArg == ObjectTypeTask {
|
||||||
|
Loading…
Reference in New Issue
Block a user