Skip to content

Commit

Permalink
Integrate auto inviter to the login page.
Browse files Browse the repository at this point in the history
If the user is not part of the instructlab org,
it will show the pop-up warning with a message
to join the org.
Popup will provide the button to send the invitation.
Once user receives the invite, it will be able to login
to the UI.

Signed-off-by: Anil Vishnoi <[email protected]>
Co-authored-by: Brent Salisbury <[email protected]>
  • Loading branch information
vishnoianil and nerdalert committed Oct 18, 2024
1 parent 15638b6 commit de2f032
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 85 deletions.
3 changes: 3 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
const nextConfig = {
reactStrictMode: true,
transpilePackages: ['@patternfly/react-core', '@patternfly/react-styles', '@patternfly/react-table', '@patternfly/react-component-groups'],
experimental: {
missingSuspenseWithCSRBailout: false,
},
};

module.exports = nextConfig;
2 changes: 1 addition & 1 deletion src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const authOptions: NextAuthOptions = {
} else if (response.status === 404) {
console.log(`User ${githubProfile.login} is not a member of the ${ORG} organization`);
logger.warn(`User ${githubProfile.login} is not a member of the ${ORG} organization`);
return `/error?error=AccessDenied`; // Redirect to custom error page
return `/login?error=NotOrgMember&user=${githubProfile.login}`; // Redirect to custom error page
} else {
console.log(`Unexpected error while authenticating user ${githubProfile.login} with ${ORG} github organization.`);
logger.error(`Unexpected error while authenticating user ${githubProfile.login} with ${ORG} github organization.`);
Expand Down
66 changes: 66 additions & 0 deletions src/app/api/invite/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// src/api/invite/route.tsx
'use server';

import { NextRequest, NextResponse } from 'next/server';

const ORG_NAME = process.env.NEXT_PUBLIC_AUTHENTICATION_ORG;
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;

export async function POST(req: NextRequest) {
try {
const body = await req.json();
const { githubUsername } = body;

console.log('Received GitHub username:', githubUsername);

if (!githubUsername) {
console.log('GitHub username is missing in the request');
return NextResponse.json({ error: 'GitHub username is required' }, { status: 400 });
}

console.log('GITHUB_TOKEN is:', GITHUB_TOKEN ? 'Loaded' : 'Not loaded');
console.log('github toke:', GITHUB_TOKEN);

// Step 1: Fetch the GitHub user details by their username
const userResponse = await fetch(`https://api.github.com/users/${githubUsername}`, {
method: 'GET',
headers: {
Authorization: `token ${GITHUB_TOKEN}`,
Accept: 'application/vnd.github.v3+json'
}
});

if (!userResponse.ok) {
const errorResponse = await userResponse.text();
console.log('Failed to fetch GitHub user ID:', errorResponse);
return NextResponse.json({ error: 'Failed to fetch GitHub user ID' }, { status: userResponse.status });
}

const userData = await userResponse.json();
const inviteeId = userData.id;

const inviteResponse = await fetch(`https://api.github.com/orgs/${ORG_NAME}/invitations`, {
method: 'POST',
headers: {
Authorization: `token ${GITHUB_TOKEN}`,
Accept: 'application/vnd.github.v3+json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
invitee_id: inviteeId
})
});

const inviteResponseBody = await inviteResponse.text();
console.log('GitHub API response status:', inviteResponse.status);

if (inviteResponse.ok) {
return NextResponse.json({ message: `Invitation sent successfully to ${githubUsername}` }, { status: 200 });
} else {
return NextResponse.json({ error: inviteResponseBody }, { status: inviteResponse.status });
}
} catch (error) {
console.error('Failed to send invitation:', error);
return NextResponse.json({ error: 'Failed to send the invitation' }, { status: 500 });
}
}
41 changes: 0 additions & 41 deletions src/app/error/error.module.css

This file was deleted.

42 changes: 0 additions & 42 deletions src/app/error/page.tsx

This file was deleted.

78 changes: 77 additions & 1 deletion src/app/login/githublogin.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Button } from '@patternfly/react-core/dist/dynamic/components/Button';
import { Text } from '@patternfly/react-core/dist/dynamic/components/Text';
import { TextContent } from '@patternfly/react-core/dist/dynamic/components/Text';
Expand All @@ -7,12 +7,67 @@ import { GridItem } from '@patternfly/react-core/dist/dynamic/layouts/Grid';
import GithubIcon from '@patternfly/react-icons/dist/dynamic/icons/github-icon';
import './githublogin.css';
import { signIn } from 'next-auth/react';
import { useRouter, useSearchParams } from 'next/navigation';
import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/components/Modal';

const GithubLogin: React.FC = () => {
const searchParams = useSearchParams();
const router = useRouter();
const [showError, setShowError] = useState(false);
const [errorMsg, setErrorMsg] = useState('Something went wrong.');
const [githubUsername, setGithubUsername] = useState<string | null>(null);

useEffect(() => {
const githubUsername = searchParams.get('user');
setGithubUsername(githubUsername);
const error = searchParams.get('error');
if (error === 'NotOrgMember') {
const errorMessage =
'You are not a member of the InstructLab Public org. Please join the InstructLab Public Organization on Github and try again.';
setErrorMsg(errorMessage);
setShowError(true);
}
}, []);

const handleGitHubLogin = () => {
signIn('github', { callbackUrl: '/' }); // Redirect to home page after login
};

const handleOnClose = () => {
setShowError(false);
router.push('/');
};

const sendInvite = async () => {
console.log('Sending invitation to:', githubUsername); // Log the GitHub username
try {
const response = await fetch('/api/invite', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ githubUsername })
});

const responseBody = await response.text();
console.log('API response body:', responseBody);

if (response.ok) {
alert('You have been invited to the GitHub organization!');
setShowError(false);
router.push('/');
} else {
console.log('Failed to send invitation:', responseBody);
alert(`Failed to send invitation: ${responseBody}`);
router.push('/');
}
} catch (error) {
console.error('Error while sending the invitation:', error);
alert('An error occurred while sending the invitation.');
router.push('/');
}
};

return (
<div className="login-page-background">
<Grid hasGutter span={12}>
Expand Down Expand Up @@ -73,6 +128,27 @@ const GithubLogin: React.FC = () => {
</div>
</GridItem>
</Grid>
{showError && (
<div>
<Modal
variant={ModalVariant.medium}
title="Please Join The InstructLab Public Org On GitHub"
titleIconVariant="warning"
isOpen={showError}
onClose={() => handleOnClose()}
actions={[
<Button key="confirm" variant="primary" onClick={() => sendInvite()}>
Send Invite to {githubUsername}
</Button>,
<Button key="cancel" variant="secondary" onClick={() => handleOnClose()}>
No, Thanks
</Button>
]}
>
<p>{errorMsg}</p>
</Modal>
</div>
)}
</div>
);
};
Expand Down

0 comments on commit de2f032

Please sign in to comment.