Skip to content

feat(auth): decouple authorization and admin layout #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f2c1182
feat(auth): add NotAuthorized and NotFound pages
jescalada Feb 4, 2025
256523f
feat(auth): add AuthProvider and PrivateRoute wrapper
jescalada Feb 4, 2025
516ed7f
chore(auth): rename userLoggedIn endpoint
jescalada Feb 4, 2025
47e95d4
chore(auth): refactor routes to use PrivateRoute guard
jescalada Feb 4, 2025
893e0b1
fix(auth): temporary fix for username edit redirect
jescalada Feb 7, 2025
d049463
fix(auth): access user admin status correctly
jescalada Feb 7, 2025
db04af6
chore(auth): refactor /admin routes into /dashboard
jescalada Feb 11, 2025
9736801
chore(auth): rename Admin files into Dashboard
jescalada Feb 11, 2025
e7ec1f0
test(auth): Add default login redirect E2E test
jescalada Feb 11, 2025
3702acd
fix(auth): fix redirect on local login
jescalada Feb 11, 2025
f2560ab
fix(auth): improve error handling on repos page
jescalada Feb 11, 2025
24ca06f
test(auth): fix failing test (login before accessing page)
jescalada Feb 11, 2025
2146bc0
test(auth): fix login command and simplify login flow
jescalada Feb 11, 2025
6b96db0
Merge branch 'oidc-implementation' into layout-auth-decoupling
jescalada Mar 10, 2025
050ba17
chore(auth): fix linter issues
jescalada Mar 10, 2025
71a5e6f
chore(deps): update dependency @finos/git-proxy to ^1.9.3 - git-proxy…
renovate[bot] Mar 26, 2025
5ceba0c
Merge pull request #956 from finos/renovate/git-proxy-plugin-samples-…
JamieSlome Mar 26, 2025
1f313ea
fix(deps): update dependency axios to ^1.8.4 - git-proxy-cli - packag…
renovate[bot] Mar 26, 2025
83e814b
Merge pull request #958 from finos/renovate/git-proxy-cli-manager
JamieSlome Mar 26, 2025
fd74b32
Merge branch 'main' into layout-auth-decoupling
jescalada Apr 2, 2025
4c4f513
fix(auth): fix issue during merge
jescalada Apr 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore(auth): refactor /admin routes into /dashboard
jescalada committed Feb 11, 2025
commit db04af6d2bd41371a218c9e0b8c6f72cd5b201b4
4 changes: 2 additions & 2 deletions cypress/e2e/repo.cy.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
describe('Repo', () => {
beforeEach(() => {
cy.visit('/admin/repo');
cy.visit('/dashboard/repo');

// prevent failures on 404 request and uncaught promises
cy.on('uncaught:exception', () => false);
@@ -18,7 +18,7 @@ describe('Repo', () => {

cy
// find the entry for finos/test-repo
.get('a[href="/admin/repo/test-repo"]')
.get('a[href="/dashboard/repo/test-repo"]')
// take it's parent row
.closest('tr')
// find the nearby span containing Code we can click to open the tooltip
6 changes: 3 additions & 3 deletions src/index.jsx
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-d
import { AuthProvider } from './ui/auth/AuthProvider';

// core components
import Admin from './ui/layouts/Admin';
import Dashboard from './ui/layouts/Dashboard';
import Login from './ui/views/Login/Login';
import './ui/assets/css/material-dashboard-react.css';
import NotAuthorized from './ui/views/Extras/NotAuthorized';
@@ -17,10 +17,10 @@ ReactDOM.render(
<AuthProvider>
<Router history={hist}>
<Routes>
<Route exact path='/admin/*' element={<Admin />} />
<Route exact path='/dashboard/*' element={<Dashboard />} />
<Route exact path='/login' element={<Login />} />
<Route exact path='/not-authorized' element={<NotAuthorized />} />
<Route exact path='/' element={<Navigate from='/' to='/admin/repo' />} />
<Route exact path='/' element={<Navigate from='/' to='/dashboard/repo' />} />
<Route path='*' element={<NotFound />} />
</Routes>
</Router>
2 changes: 1 addition & 1 deletion src/proxy/processors/push-action/blockForAuth.js
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ const exec = async (req, action) => {
'\n\n\n' +
`\x1B[32mGitProxy has received your push ✅\x1B[0m\n\n` +
'🔗 Shareable Link\n\n' +
`\x1B[34m${url}/admin/push/${action.id}\x1B[0m` +
`\x1B[34m${url}/dashboard/push/${action.id}\x1B[0m` +
'\n\n\n';
step.setAsyncBlock(message);

18 changes: 9 additions & 9 deletions src/routes.jsx
Original file line number Diff line number Diff line change
@@ -36,55 +36,55 @@ const dashboardRoutes = [
name: 'Repositories',
icon: RepoIcon,
component: (props) => <PrivateRoute component={RepoList} />,
layout: '/admin',
layout: '/dashboard',
visible: true,
},
{
path: '/repo/:id',
name: 'Repo Details',
icon: Person,
component: (props) => <PrivateRoute component={RepoDetails} />,
layout: '/admin',
layout: '/dashboard',
visible: false,
},
{
path: '/push',
name: 'Dashboard',
icon: Dashboard,
component: (props) => <PrivateRoute component={OpenPushRequests} />,
layout: '/admin',
layout: '/dashboard',
visible: true,
},
{
path: '/push/:id',
name: 'Open Push Requests',
icon: Person,
component: (props) => <PrivateRoute component={PushDetails} />,
layout: '/admin',
layout: '/dashboard',
visible: false,
},
{
path: '/profile',
name: 'My Account',
icon: AccountCircle,
component: (props) => <PrivateRoute component={User} />,
layout: '/admin',
layout: '/dashboard',
visible: true,
},
{
path: '/user',
path: '/admin/user',
name: 'Users',
icon: Group,
component: (props) => <PrivateRoute adminOnly component={UserList} />,
layout: '/admin',
layout: '/dashboard',
visible: true,
},
{
path: '/user/:id',
path: '/admin/user/:id',
name: 'User',
icon: Person,
component: (props) => <PrivateRoute adminOnly component={User} />,
layout: '/admin',
layout: '/dashboard',
visible: false,
},
];
2 changes: 1 addition & 1 deletion src/service/routes/auth.js
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ router.get('/oidc/callback', (req, res, next) => {
return res.status(401).end();
}
console.log('Logged in successfully. User:', user);
return res.redirect(`${uiHost}:${uiPort}/admin/profile`);
return res.redirect(`${uiHost}:${uiPort}/dashboard/profile`);
});
})(req, res, next);
});
2 changes: 1 addition & 1 deletion src/ui/components/Sidebar/Sidebar.jsx
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ export default function Sidebar(props) {
);
const brand = (
<div className={classes.logo}>
<a style={{ textDecoration: 'none' }} href='/admin/repo'>
<a style={{ textDecoration: 'none' }} href='/dashboard/repo'>
<div style={{ textAlign: 'center' }}>
<img
style={{ verticalAlign: 'middle', filter: 'brightness(0) invert(1)' }}
8 changes: 4 additions & 4 deletions src/ui/views/Login/Login.jsx
Original file line number Diff line number Diff line change
@@ -76,10 +76,10 @@ export default function UserProfile() {
}

if (gitAccountError) {
return <Navigate to={{ pathname: '/admin/profile' }} />;
return <Navigate to={{ pathname: '/dashboard/profile' }} />;
}
if (success) {
return <Navigate to={{ pathname: '/admin/profile', state: { authed: true } }} />;
return <Navigate to={{ pathname: '/dashboard/profile', state: { authed: true } }} />;
}

return (
@@ -169,8 +169,8 @@ export default function UserProfile() {
<div style={{ textAlign: 'center', opacity: 0.9, fontSize: '12px' }}>
<Badge overlap='rectangular' color='error' badgeContent={'NEW'} />{' '}
<span style={{ paddingLeft: '20px' }}>
View our <a href='/admin/push'>open source activity feed</a> or{' '}
<a href='/admin/repo'>scroll through projects</a> we contribute to
View our <a href='/dashboard/push'>open source activity feed</a> or{' '}
<a href='/dashboard/repo'>scroll through projects</a> we contribute to
</span>
</div>
</GridItem>
2 changes: 1 addition & 1 deletion src/ui/views/OpenPushRequests/components/PushesTable.jsx
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ export default function PushesTable(props) {
const [isError, setIsError] = useState(false);
const navigate = useNavigate();

const openPush = (push) => navigate(`/admin/push/${push}`, { replace: true });
const openPush = (push) => navigate(`/dashboard/push/${push}`, { replace: true });

useEffect(() => {
const query = {};
10 changes: 5 additions & 5 deletions src/ui/views/PushDetails/PushDetails.jsx
Original file line number Diff line number Diff line change
@@ -48,20 +48,20 @@ export default function Dashboard() {
const authorise = async (attestationData) => {
await authorisePush(id, setMessage, setUserAllowedToApprove, attestationData);
if (isUserAllowedToApprove) {
navigate('/admin/push/');
navigate('/dashboard/push/');
}
};

const reject = async () => {
await rejectPush(id, setMessage, setUserAllowedToReject);
if (isUserAllowedToReject) {
navigate('/admin/push/');
navigate('/dashboard/push/');
}
};

const cancel = async () => {
await cancelPush(id, setAuth, setIsError);
navigate(`/admin/push/`);
navigate(`/dashboard/push/`);
};

if (isLoading) return <div>Loading...</div>;
@@ -178,15 +178,15 @@ export default function Dashboard() {
htmlColor='green'
/>
</span>
<a href={`/admin/user/${data.attestation.reviewer.username}`}>
<a href={`/dashboard/user/${data.attestation.reviewer.username}`}>
<img
style={{ width: '45px', borderRadius: '20px' }}
src={`https://github.com/${data.attestation.reviewer.gitAccount}.png`}
/>
</a>
<div>
<p>
<a href={`/admin/user/${data.attestation.reviewer.username}`}>
<a href={`/dashboard/user/${data.attestation.reviewer.username}`}>
{data.attestation.reviewer.gitAccount}
</a>{' '}
approved this contribution
4 changes: 2 additions & 2 deletions src/ui/views/PushDetails/components/AttestationView.jsx
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ export default function AttestationView(props) {
<p style={{ fontSize: '15px', paddingLeft: '34px' }}>
Prior to making this code contribution publicly accessible via GitHub, this code
contribution was reviewed and approved by{' '}
<a href={`/admin/user/${props.data.reviewer.username}`}>
<a href={`/dashboard/admin/user/${props.data.reviewer.username}`}>
{props.data.reviewer.gitAccount}
</a>
. As a reviewer, it was their responsibility to confirm that open sourcing this
@@ -72,7 +72,7 @@ export default function AttestationView(props) {
<DialogContent>
<p>
<span>
<a href={`/admin/user/${props.data.reviewer.username}`}>
<a href={`/dashboard/admin/user/${props.data.reviewer.username}`}>
{props.data.reviewer.gitAccount}
</a>{' '}
approved this contribution{' '}
6 changes: 3 additions & 3 deletions src/ui/views/RepoDetails/RepoDetails.jsx
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ export default function RepoDetails() {

const removeRepository = async (name) => {
await deleteRepo(name);
navigate('/admin/repo', { replace: true });
navigate('/dashboard/repo', { replace: true });
};

const refresh = () => getRepo(setIsLoading, setData, setAuth, setIsError, repoName);
@@ -151,7 +151,7 @@ export default function RepoDetails() {
return (
<TableRow key={row}>
<TableCell align='left'>
<a href={`/admin/user/${row}`}>{row}</a>
<a href={`/dashboard/admin/user/${row}`}>{row}</a>
</TableCell>
{user.admin && (
<TableCell align='right' component='th' scope='row'>
@@ -196,7 +196,7 @@ export default function RepoDetails() {
return (
<TableRow key={row}>
<TableCell align='left'>
<a href={`/admin/user/${row}`}>{row}</a>
<a href={`/dashboard/admin/user/${row}`}>{row}</a>
</TableCell>
{user.admin && (
<TableCell align='right' component='th' scope='row'>
2 changes: 1 addition & 1 deletion src/ui/views/RepoList/Components/RepoOverview.jsx
Original file line number Diff line number Diff line change
@@ -591,7 +591,7 @@ export default function Repositories(props) {
<TableRow>
<TableCell>
<div style={{ padding: '15px' }}>
<a href={`/admin/repo/${props.data.name}`}>
<a href={`/dashboard/repo/${props.data.name}`}>
<span style={{ fontSize: '17px' }}>
{props.data.project}/{props.data.name}
</span>
2 changes: 1 addition & 1 deletion src/ui/views/RepoList/Components/Repositories.jsx
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ export default function Repositories(props) {
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const navigate = useNavigate();
const openRepo = (repo) => navigate(`/admin/repo/${repo}`, { replace: true });
const openRepo = (repo) => navigate(`/dashboard/repo/${repo}`, { replace: true });
const { user } = useContext(UserContext);

useEffect(() => {
4 changes: 2 additions & 2 deletions src/ui/views/User/User.jsx
Original file line number Diff line number Diff line change
@@ -52,15 +52,15 @@ export default function Dashboard() {

if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Something went wrong ...</div>;
if (!auth && window.location.pathname === '/admin/profile') {
if (!auth && window.location.pathname === '/dashboard/profile') {
return <Navigate to='/login' />;
}

const updateProfile = async () => {
try {
data.gitAccount = escapeHTML(gitAccount);
await updateUser(data);
navigate(`/admin/profile`);
navigate(`/dashboard/profile`);
} catch {
setIsError(true);
}
2 changes: 1 addition & 1 deletion src/ui/views/UserList/Components/UserList.jsx
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ export default function UserList(props) {
const [isError, setIsError] = useState(false);
const navigate = useNavigate();

const openUser = (username) => navigate(`/admin/user/${username}`, { replace: true });
const openUser = (username) => navigate(`/dashboard/admin/user/${username}`, { replace: true });

useEffect(() => {
const query = {};